Codeforces 1108F MST Unification(最小生成树性质)

题目链接:MST Unification

题意:给定一张连通的无向带权图。存在给边权加一的操作,求最少操作数,使得最小生成树唯一。

题解:最小生成树在算法导论中有这个性质:

把一个连通无向图的生成树边按权值递增排序,称排好序的边权列表为有序边权列表,则任意两棵最小生成树的有序边权列表是相同的。(算法导论23.1-8)

通过这个性质,考虑边权相同的边,把这些边中能够替代的边计算出来即可。

 1 #include <set>
 2 #include <map>
 3 #include <queue>
 4 #include <deque>
 5 #include <stack>
 6 #include <cmath>
 7 #include <cstdio>
 8 #include <vector>
 9 #include <string>
10 #include <cstring>
11 #include <fstream>
12 #include <iostream>
13 #include <algorithm>
14 using namespace std;
15 
16 #define eps 1e-8
17 #define pb push_back
18 #define PI acos(-1.0)
19 #define INF 0x3f3f3f3f
20 #define clr(a,b) memset(a,b,sizeof(a)
21 #define bugc(_) cerr << (#_) << " = " << (_) << endl
22 #define FAST_IO ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL)
23 
24 typedef long long ll;
25 typedef unsigned long long ull;
26 const int N=2e5+10;
27 
28 int fa[N];
29 struct edge{
30     int u,v,w;
31 }e[N];
32 
33 int fi(int x){
34     return fa[x]==x?x:fa[x]=fi(fa[x]);
35 }
36 
37 bool cmp(edge x,edge y){
38     return x.w<y.w;
39 }
40 
41 int main(){
42     int n,m,ans=0;
43     scanf("%d%d",&n,&m);
44     for(int i=1;i<=n;i++) fa[i]=i;
45     for(int i=1;i<=m;i++){
46         scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
47     }
48     sort(e+1,e+1+m,cmp);
49     for(int i=1;i<=m;){
50         int j=i;
51         while(e[j].w==e[i].w) j++;
52         for(int k=i;k<j;k++){
53             int fx=fi(e[k].u),fy=fi(e[k].v);
54             if(fx!=fy) ans++;
55         }
56         for(int k=i;k<j;k++){
57             int fx=fi(e[k].u),fy=fi(e[k].v);
58             if(fx!=fy){
59                 fa[fx]=fy;
60                 ans--;
61             }
62         }
63         i=j;
64     }
65     printf("%d
",ans);
66     return 0;
67 }
View Code
原文地址:https://www.cnblogs.com/pavtlly/p/10321531.html