
cf 1108f 如何增加边权得到唯一的最小生成树 kruskal
发布日期:2021-05-06 15:25:30
浏览次数:25
分类:精选文章
本文共 1228 字,大约阅读时间需要 4 分钟。
题意:
n个点m条无向边的连通图,要求你给尽可能小的边的权值加1,使得图的最小生成树唯一。
题解:
1.造成多种最小生成的冲突边是权值相同且连通块相同的边。
2.kruskal的思路做:
(1)把边按权值排序。
(2)找出边权值相同的区间[i,j),遍历[i,j)记录连接两个连通块的边的数目cnt,然后再遍历一遍[i,j),若边连接两个连通块,那么用这条边连接两个连通块,并且cnt --,与该边权值相同且连接的两个连通块相同的冲突边就被算进去了。
(3)将cnt累加起来即为答案。
#include#define N 200005using namespace std ;struct Edge{ int u , v , w ;} edge[N] ;int n , m ;bool vis[N] ;int pre[N] ;int find(int x){ if(x == pre[x]) return pre[x] ; pre[x] = find(pre[x]) ; return pre[x] ;}bool cmp(Edge a , Edge b){ return a.w < b.w ;}int main(){ int i , j , k ; int u , v , w ; Edge a ; int cnt ; int ans = 0 ; scanf("%d%d" , &n , &m) ; for(i = 0 ; i < m ; i ++) { scanf("%d%d%d" , &u , &v , &w) ; a.u = u ; a.v = v ; a.w = w ; edge[i] = a ; } sort(edge , edge + m , cmp) ; for(i = 1 ; i <= n ; i ++) pre[i] = i ; for(i = 0 ; i < m ; i ++) { j = i ; while(edge[j].w == edge[i].w && j < m) j ++ ; cnt = 0 ; for(k = i ; k < j ; k ++) if(find(edge[k].u) != find(edge[k].v)) cnt ++ ; for(k = i ; k < j ; k ++) if(find(edge[k].u) != find(edge[k].v)) { pre[find(edge[k].u)] = find(edge[k].v) ; cnt -- ; } ans += cnt ; i = j - 1 ; } printf("%d\n" , ans) ;}
发表评论
最新留言
感谢大佬
[***.8.128.20]2025年04月02日 07时59分47秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
INotifyPropertyChanged 接口
2019-03-06
一些有趣的线段树玩法
2019-03-06
Go语言中的数组与数组切片
2019-03-06
操作系统启动过程
2019-03-06
进程管理
2019-03-06
物理层
2019-03-06
内建函数
2019-03-06
C/C++分文件编写
2019-03-06
80x86指令系统-1-数据传送指令
2019-03-06
C语言+easyX图形库的推箱子实现
2019-03-06
结构体内存偏移量
2019-03-06
应用程序与dll的静态库通信
2019-03-06
反汇编-流程控制语句-2-循环控制语句分析
2019-03-06
调试vs2019代码的流程
2019-03-06
游戏外挂基础-概述
2019-03-06
脱壳与加壳-加壳-6-代码实现加密导入表
2019-03-06
Typora配置PicGo时,提示Failed to fetch
2019-03-06
ASP.NET CORE MVC 实现减号分隔(Kebab case)样式的 URL
2019-03-06