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 }

 

posted @ 2019-04-15 15:00  VBL  阅读(160)  评论(0编辑  收藏  举报