Codeforces Round #535 (Div. 3) F
F. MST Unification
题意:
给你n个顶点,m条边;保证没有重边,其中存在多个MST(最小生成树),
你可以修改一些边的权值,让其中有且仅有一个最小生成树,求最少操作的边数。
思路:
最小生成树算法的加工,我们从kruskal算法入手,kruskal就是先对边排序,
然后遍历边不断加入一些合格边来完善最小生成树
那么在这个过程中,如果边的权值一样的话,就会产生多种MST,但是这里
不能仅仅只是累计相同权值的边数,因为与合格边相同权值的边可能可以选择
多条。
所以我们可以将所有符合的边累加起来,然后减去(n-1)就是与合格边冲突的边
,也就是答案了
#include<bits/stdc++.h> using namespace std; #define N 200005 int n,m; struct node { int u,v,w; bool operator <(const node &p) const{ return w<p.w; } }edge[N]; int fa[N]; int Find(int x) { if(x==fa[x]) return x; else return fa[x]=Find(fa[x]); } int main() { while(~scanf("%d %d",&n,&m)) { for(int i=0;i<m;i++) scanf("%d %d %d",&edge[i].u,&edge[i].v,&edge[i].w); for(int i=1;i<=n;i++) fa[i]=i; sort(edge,edge+m); int ans=0; int L=0; for(int i=0;i<m;i++) { int u=edge[i].u,v=edge[i].v; u=Find(u),v=Find(v); if(u!=v) ans++; if(i+1<m && edge[i].w!=edge[i+1].w) { for(int j=L;j<=i;j++) { int u=edge[j].u,v=edge[j].v; u=Find(u),v=Find(v); if(u!=v) fa[u]=v; } L=i+1; } } printf("%d\n",ans-(n-1)); } }