首页 > 代码库 > 克鲁斯卡尔算法+并查集

克鲁斯卡尔算法+并查集

算法要点:Kruskal算法的最难点在于怎样判断加入边(x,y)后是否形成了环。

问题可化为:判断边(x,y)的两个顶点x,y在图(实际是森林)mst中最否已经连通。如果已经连通,加入边将形成环;否则,不形成环。

 

在kruskal算法中,要用到并查集的合并和查找

并查集:

 1 int getfa(int k)        //找到最祖先 2 { 3     if(fa[k]==k)    return k; 4     fa[k]=getfa(fa[k]); 5     return fa[k]; 6 } 7  8 void merge(int x,int y)       //合并祖先 9 {10     int fx=getfa(x);11     int fy=getfa(y);12     fa[fx]=fy;13 }14 15 bool judge(int x, int y)       //判断是不是一个祖先16 {17     int fx=getfa(x);18     int fy=getfa(y);19     return fx==fy;20 }

 

 kruskal算法核心:

 1 for(int i=1;i<=n;i++) 2         fa[i]=i; 3 sort(e+1,e+1+len,mys); 4 int cal=0; 5 for(int i=1;i<=len;i++) 6 { 7     int v=getfa(e[i].x); 8     int u=getfa(e[i].y); 9     if(v!=u)10     {11         merge(v,u);12                 //根据题意添加13         if(++cal==n-1)14         {15             break;16         }17     }18 }

 

输入:

 1 int fa[maxn]; 2 int len=0; 3 struct node 4 { 5     int x,y,v; 6 }e[maxn]; 7  8 void init(int xx,int yy,int vv) 9 {10     if(yy<0||yy>n*m)    return;11     e[++len].y=yy;12     e[len].x=xx;e[len].v=vv;13 }14 15 int main()16 {17     memset(e,0,sizeof(e));18     cin>>n>>m;19     for(int i=1;i<=m;i++)20     {21         int xx,yy,vv;22         cin>>xx>>yy>>vv;23         init(xx,yy,vv);24         init(yy,xx,vv);25     }

 

克鲁斯卡尔算法+并查集