ZOJ 1203 Swordfish Kruskal算法求最小生成树

就是如题的做法,在一个连通图中找一条最小生成树,Kruskal的思想就是先根据所有边的权值按小到大排序,然后依次选择边进最小生成树里,但是要排除该边加进去后出现了环,生成树里是不能有环的,这样的边就不能加入,在挑选了n-1(n为图中点的个数)条边后就结束,可以证明这样构造出来的图就是最小生生成树。

再判断是否会出现环时用到并查集。

int temp = parent[r1] +parent[r2];//两根结点所带结点的总数,因为写错了这句,我检查了N久,砸墙,我很激动地写成了 int temp = Find(r1)+Find(r2);

然后各种程序各种混乱了。还有一点因为没有看见说每两个case中间要输出一个空行,然后PE了,然后改成在每个case后输两个换行符,结果还是PE,郁闷,最后只好在case输出结果之前写了一句if(不是第一个case) 输出换行。。。。。

贴代码如下:

View Code
  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <cmath>
  5 #define MAXN  120
  6 #define MAXM 6000
  7 using namespace std;
  8 int n,m;  //n为城市的个数,m为边的数目m = C(n,2)
  9 struct point   //平面上的一个点
 10 {
 11     double x,y;
 12 } city[MAXN];  //存各个城市的位置
 13 struct ArcNode
 14 {
 15     int u,v;  //一条边的起点和终点
 16     double w;  //边的长度,也就是两城市间的距离
 17     bool operator <(const ArcNode & other) const
 18     {
 19         if(w < other.w) return true;
 20         else return false;
 21     };
 22 } edge[MAXM];  //存边
 23 int parent[MAXN];  //用于并查集
 24 double dis(point a,point b)  //求两城市间距离函数
 25 {
 26     double d =sqrt((a.x - b.x) *(a.x - b.x)  + (a.y - b.y) *(a.y - b.y) );
 27     return d;
 28 }
 29 int Find(int x)
 30 {
 31     int s;
 32     for(s = x; parent[s] >= 0; s = parent[s]);
 33     while(s != x)
 34     {
 35         int temp = parent[x];
 36         parent[x] = s;
 37         x = temp;
 38     }
 39     return s;
 40 }
 41 void Union(int x,int y)
 42 {
 43     int r1 = Find(x);
 44     int r2 = Find(y);
 45     int temp = parent[r1] +parent[r2];//两根结点所带结点的总数
 46     if(parent[r1] > parent[r2])
 47     {
 48         parent[r1] = r2;
 49         parent[r2] = temp;
 50     }
 51     else
 52     {
 53         parent[r2] = r1;
 54         parent[r1] = temp;
 55     }
 56 }
 57 double  Kruskal()
 58 {
 59     int i;
 60     for(i=0; i<n; i++)
 61         parent[i] = -1;
 62     int num =0;
 63     double sum = 0;
 64     sort(edge,edge+m);
 65     for(i=0; i<m; i++)
 66     {
 67         int u = edge[i].u;
 68         int v = edge[i].v;
 69         if(Find(u) != Find(v))
 70         {
 71             Union(u,v);
 72             sum += edge[i].w;
 73             num++;
 74         }
 75         if(num >= n-1) break;
 76     }
 77     return sum;
 78 }
 79 int main()
 80 {
 81 //    freopen("in.cpp","r",stdin);
 82     int ser = 0;
 83     int i,j;
 84     while(~scanf("%d",&n) && n!=0)
 85     {
 86         for(i=0; i<n; i++)
 87             scanf("%lf%lf",&city[i].x,&city[i].y);
 88         m = 0;
 89         for(i=0; i<n; i++)
 90         {
 91             for(j=i+1; j<n; j++)
 92             {
 93                 edge[m].u = i;
 94                 edge[m].v = j;
 95                 edge[m].w = dis(city[i],city[j]);
 96                 m++;
 97             }
 98         }
 99         ser++;
100         if( ser != 1) printf("\n");
101         printf("Case #%d:\n",ser);
102         printf("The minimal distance is: %.2lf\n",Kruskal());
103     }
104     return 0;
105 }

 

 

 

posted on 2013-03-31 00:54  allh123  阅读(193)  评论(0编辑  收藏  举报

导航