[关闭]
@zhangche0526 2017-02-23T08:50:45.000000Z 字数 1923 阅读 858

Kruskal求最小(大)生成树

模板

思路:将边排序,依次向并查集里加边,并且保证此边连接的两个结点不在一个并查集里,加到N-1(N为图中结点数)条边时,就生成了最小生成树

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cmath>
  4. #include<cstring>
  5. #include<algorithm>
  6. using namespace std;
  7. int ecnt;
  8. struct node{int from,to,value;} edge[100001];
  9. void add(int from,int to,int value)
  10. {
  11. ecnt++;
  12. edge[ecnt].from=from;
  13. edge[ecnt].to=to;
  14. edge[ecnt].value=value;
  15. }
  16. int fath[100001];
  17. int getfath(int x)
  18. {
  19. if(fath[x]==x) return x;
  20. return fath[x]=getfath(fath[x]);
  21. }
  22. void unionset(int x,int y){fath[getfath(x)]=getfath(y);}
  23. int cmp(const node &a,const node &b)
  24. {
  25. if(a.value<b.value) return true;
  26. else return false;
  27. }
  28. long long mstv=0,biancnt=0;
  29. int main()
  30. {
  31. ios::sync_with_stdio(false);
  32. int n,m;
  33. cin>>n>>m;
  34. int from,to,value;int x;
  35. for(int i=1;i<=m;i++)
  36. {
  37. cin>>from>>to>>value;
  38. add(from,to,value);
  39. }
  40. for(int i=1;i<=n;i++) fath[i]=i;
  41. sort(edge+1,edge+ecnt+1,cmp);
  42. for(int i=1;i<=m;i++)
  43. {
  44. if(getfath(edge[i].from)!=getfath(edge[i].to))
  45. {
  46. unionset(edge[i].from,edge[i].to);
  47. mstv+=edge[i].value;
  48. biancnt++;
  49. }
  50. if(biancnt==n-1) break;
  51. }
  52. cout<<mstv;
  53. return 0;
  54. }

例题

UVa1395 Slim_Span


所谓的Slim Span即为最大边与最小边差值最小的生成树,与最小生成树问题的思路相似

先对边升序排序,对于一个连续的边区间,从小到大枚举L,对于每个L,从小到大枚举R,依次向并查集里加边,加个判断:如果目前的这些边已经使得图连通,就停止枚举,并更新最小值。


  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. using namespace std;
  5. const int MAXN=100,MAXM=50*99,INF=1<<30;
  6. struct node2{int u,v,w;} a[MAXM+1];int acnt;
  7. void add2(int u,int v,int w){++acnt,a[acnt].u=u,a[acnt].v=v,a[acnt].w=w;}
  8. int fa[MAXN+1];
  9. int getfa(int x)
  10. {
  11. if(fa[x]==x) return x;
  12. return fa[x]=getfa(fa[x]);
  13. }
  14. void join(int x,int y)
  15. {
  16. fa[getfa(x)]=getfa(y);
  17. }
  18. bool cmp(const node2 & a,const node2 & b){return a.w<b.w;}
  19. int N,M;
  20. int main()
  21. {
  22. int i;
  23. while(cin>>N>>M&&N)
  24. {
  25. acnt=0;
  26. for(i=1;i<=N;i++) fa[i]=i;
  27. for(i=1;i<=M;i++)
  28. {
  29. int u,v,w;
  30. scanf("%d%d%d",&u,&v,&w);
  31. add2(u,v,w);
  32. }sort(a+1,a+M+1,cmp);
  33. int L,R;
  34. int minv=INF;
  35. for(L=1;L<=M-(N-1)+1;L++)
  36. {
  37. for(i=1;i<=N;i++) fa[i]=i;
  38. int times=0;
  39. for(R=L;R<=M;R++)
  40. if(getfa(a[R].u)!=getfa(a[R].v))
  41. {
  42. join(a[R].u,a[R].v);
  43. ++times;
  44. if(times==N-1)
  45. {
  46. minv=min(minv,a[R].w-a[L].w);
  47. break;
  48. }
  49. }
  50. }
  51. if(minv==INF) cout<<-1<<endl;
  52. else cout<<minv<<endl;
  53. }
  54. return 0;
  55. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注