Codeforces Round #535 F-MST Unification
题目大意:
给定n m 为图中的点数n和边数m
给定m条边的信息 u v w 为u点到v点有一条长度为w的边
图中无环无重边
这个图的MST的花费为k 但可能存在多种花费为k的MST的方案
此时对图中的边进行操作 可增大权重或翻倍增大权重
要求只保留图中的一种花费为k的MST方案时 需要对最少多少条边进行操作
1.原本的kruskal 会选出构成MST的最短的n-1条边
即在n=5边长度为 1 2 2 3 4 4 5 6 的图中
原本会选出4条 1 2 3 4 (能构成1种MST的方案)
2.这个方法会记录到最短的n-1条边和与这些边长度相等的边
现在会选出6条 1 2 2 3 4 4 (能构成多种MST方案)
3.此时只保留一种MST方案的话需4条(n-1条)边
则需要对多出的6-4=2条边进行操作
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> #define INF 0x3f3f3f3f #define LL long long using namespace std; const int N=2e5+5; int n, m; struct EDGE { int u,v,w; bool operator <(const EDGE& p)const { return w<p.w; } }e[N]; int fa[N]; int getfa(int u) { if(fa[u]==u) return u; else return fa[u]=getfa(fa[u]); } int main() { while(~scanf("%d%d",&n,&m)) { for(int i=0;i<m;i++) scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w); sort(e,e+m); for(int i=1;i<=n;i++) fa[i]=i; int ans=0, L=0; for(int i=0;i<m;i++) { int u=getfa(e[i].u), v=getfa(e[i].v); if(u!=v) ans++; if(i+1<m and e[i+1].w!=e[i].w) { for(int j=L;j<=i;j++) { u=getfa(e[j].u), v=getfa(e[j].v); if(u!=v) fa[u]=v; } L=i+1; } } printf("%d\n",ans-(n-1)); /// 去掉唯一的的MST所需的n-1条边 } return 0; }