【模板】最小生成树(kruscal)
//洛谷P3366
(其中所应用的并查集原理请见http://www.cnblogs.com/XjzLing/p/7943363.html)
这里选用Kruscal的方法:先将每一个点用并查集记录它们的祖先,用fa[i]来表示
然后将边按照权重,从小到大排序,这里选用sort的cmp。
然后,从小到大遍历边权,如果遍历到一条边的所连的两个结点不在同一集合,就将这两个点连上,ans+=G[i].val即可。
等连到n-1条边时,该图已经成为一颗树,即输出答案
#include<algorithm> #include<iostream> #include<cstdio> #define maxn 200000 + 10 using namespace std; int n,m,ans,num; int fa[maxn]; struct edge{ int frm,to,val; }G[maxn]; //记录边的信息:起点,终点,权 void init(){ for(int i=1;i<=n;i++) fa[i]=i; }//并查集预处理 bool cmp(edge a,edge b){ return a.val<b.val; }// 用于sort的cmp函数 int find(int x){ if(x==fa[x]) return x; else return fa[x]=find(fa[x]); }//并查集找祖先 bool merge(edge a){ if(find(a.frm)!=find(a.to)){ fa[fa[a.to]]=find(a.frm); return true; } return false; }//并查集连边 int main(){ scanf("%d%d",&n,&m); init(); for(int i=1;i<=m;i++) scanf("%d%d%d",&G[i].frm,&G[i].to,&G[i].val); sort(G,G+m,cmp);//将边权从小到大排序 for(int i=1;i<=m && num<n-1;i++) if(merge(G[i])){ ans+=G[i].val; num++; }//Kruscal操作 if(num==n-1) printf("%d",ans); else printf("orz"); return 0; }