Kruskal算法
适用范围
最小生成树问题
思路
按照边的权值从小到大排序,然后在不产生圈的前提下不断选取边加入生成树中.判断加入一条边后是否产生圈,只需判断边的两个端点是否已经在一个联通块中,这个过程可以用并查集高效实现.复杂度(ElogV)E边V点.
代码
1 //并查集代码 2 int par[MAX]; 3 int rank[MAX]; 4 5 void init(int n) //顶点编号从1开始 6 { 7 for(int i=1;i<=n;i++) 8 par[i]=i; 9 return ; 10 } 11 12 int find(int x) 13 { 14 if(par[x]==x) return x; 15 else return par[x]=find(par[x]); 16 } 17 18 void unite(int x,int y) 19 { 20 x=find(x),y=find(y); 21 if(x==y) return ; 22 if(rank[x]<rank[y]) par[x]=y; 23 else 24 { 25 par[y]=x; 26 if(rank[x]==rank[y]) rank[x]++; 27 } 28 return ; 29 } 30 //分割线 31 //Kruskal代码 32 struct edge{int s,t,cost}es[MAX]; 33 int n,m; 34 35 bool cmp(edge a,edge b) 36 { 37 return a.cost<b.cost; 38 } 39 40 int kruskal(void) 41 { 42 sort(es,es+m,cmp); 43 init(n); 44 int ans=0; 45 for(int i=0;i<m;i++) 46 { 47 if(find(es[i].s)!=find(es[i].t)) 48 { 49 unite(es[i].s,es[i].t); 50 ans+=es[i].cost; 51 } 52 } 53 return ans; 54 }