POJ1861-Kruskal算法

来源:互联网 发布:化妆品成分分析软件 编辑:程序博客网 时间:2024/05/16 17:57

之前也写过Kruskal算法,到今天才发现 原来以前的写错了。(也不能说完全错,只是效率好低)。

 

以前忽视的地方主要有两点,一是Kruskal算法,一般先对边从小到大排好序,然后从小到大区边。

这样的话,排完序以后就只要一个循环就可以走完。

二是 并查集的路径压缩,我以前对并查集合并是遍历所有的结点对两个集合合并,

而正确的做法应该是这样

Cpp代码  收藏代码
  1. int flindfather(int a)  
  2. {  
  3. if(a==father[a])  
  4. return a;  
  5. else   
  6. return findfather(father[a]);  
  7. }  

 

而其实我们还可以进行路径压缩,这才是并查集的核心所在

只要将上面的代码改写一行,就能起到很好的效果

Java代码  收藏代码
  1. int flindfather(int a)  
  2. {  
  3. if(a==father[a])  
  4. return a;  
  5. else   
  6. return father[a]=findfather(father[a]);  
  7. }  

 

下面是1861的代码

Cpp代码  收藏代码
  1. #include<iostream>  
  2. #include <algorithm>  
  3. using namespace std;  
  4. #define MAXSIZE 30010  
  5. #define INF 9000100  
  6. int n,m;  
  7. int father[MAXSIZE];//并查集  
  8. int head[MAXSIZE];  
  9. int next[MAXSIZE];  
  10. int e;  
  11.   
  12. struct node{  
  13.     int u;  
  14.     int v;  
  15.     int w;  
  16. };  
  17. node edge[MAXSIZE];  
  18. node medge[MAXSIZE];  
  19. int num;  
  20. int ansmax,anstot;  
  21. //判断两点是否属于同一集合  
  22. int judge(int a,int b)  
  23. {  
  24.     if(father[a]==father[b])//同一集合  
  25.         return 1;  
  26.     return 0;  
  27. }  
  28. bool cmp(node &a,node &b)  
  29. {  
  30.     return a.w<b.w;  
  31. }  
  32. int findset(int a)  
  33. {  
  34.     if(a==father[a])  
  35.         return a;  
  36.     else   
  37.         return father[a]=findset(father[a]);  
  38. }  
  39. void kruskal()  
  40. {  
  41.     sort(edge,edge+e,cmp);  
  42.     int i,j;  
  43.     num=0;  
  44.     ansmax=anstot=0;  
  45.     for(i=0;i<2*m;i++)  
  46.         father[i]=i; //初始时 每个元素属于不同的集合  
  47.       
  48.     for(i=0;i<2*m;i++)  
  49.     {  
  50.         if(findset(edge[i].u)!=findset(edge[i].v))//如果不属于同一集合  
  51.         {  
  52.             ansmax=ansmax>edge[i].w?ansmax:edge[i].w;  
  53.             medge[num++]=edge[i];  
  54.             int tu=edge[i].u;//将所有与v一个集合的全部并入u的集合  
  55.             int tv=edge[i].v;  
  56.             father[findset(tv)]=findset(tu);  
  57.         }  
  58.           
  59.     }  
  60.   
  61. }  
  62. void addnode(int u,int v,int w)  
  63. {  
  64.     edge[e].u=u;  
  65.     edge[e].v=v;  
  66.     edge[e].w=w;  
  67.     next[e]=head[u];  
  68.     head[u]=e++;  
  69. }  
  70. int main()  
  71. {  
  72.     //freopen("in.txt","r",stdin);  
  73.     while(scanf("%d%d",&n,&m)!=EOF)  
  74.     {  
  75.         e=0;  
  76.         int t1=m;  
  77.         while(t1--)  
  78.         {  
  79.             int a,b,c;  
  80.             scanf("%d%d%d",&a,&b,&c);  
  81.             addnode(a,b,c);  
  82.             addnode(b,a,c);  
  83.         }  
  84.         kruskal();  
  85.         printf("%d\n",ansmax);  
  86.         printf("%d\n",num);  
  87.         for(int i=0;i<num;i++)  
  88.             printf("%d %d\n",medge[i].u,medge[i].v);  
  89.     }  
  90. }  

 

 

 

0 0