POJ2349(最小生成树)

        题意:有两种不同的通信技术,有卫星通信的两个城市之间可以任意联络,但用无线电通信的城市只能和距离不超过D的城市联系。无线电的能力越高(即传输距离D越大),花费就越大。已知无线电的数目m,让求最小的D。

     刚看完题目时,很迷茫,不知道该往哪去想,直到老师提醒我们用最小生成树解时,我才恍然大悟。这道题设计的真得很巧妙,如果不细心看题,及对最小生成树不熟练时,根本不知道从何下手。看来我练得还不到家,仍需继续努力。

     思路:先求出每两个顶点之间的距离,(注意:是double类型的),然后用普里姆算法(Prim)求最小生成树。由于无线电的数目已给出m,需要把最小生成树分成m份,即删除m-1条边,得到m个连通分量。关键是删除哪些边呢,题目要求最小的D,故把构成最小生成树的边从大到小排序,删除前m-1条边,第m条边即所要求的最小D。其实只要思路清晰,很容易就把这道题A了。

代码如下:

View Code
 1 #include<iostream>
 2 #include<cmath>
 3 #include<algorithm>
 4 using namespace std;
 5 #define Max 501
 6 double map[Max][Max],d[Max];
 7 int n,i,j;
 8 struct{
 9     int x,y;
10 }point[Max];
11 //记录从顶点集U到V-U的代价最小的边的辅助数组定义
12 struct{
13     int adjvex;
14     double lowcost;
15 }closedge[Max];
16 bool cmp(double a,double b)//从大到小偏序
17 {
18     return a>b;
19 }
20 //用普里姆算法从第k个顶点出发构造网G的最小生产树T
21 void prim(int k)
22 {
23     for(j=1;j<=n;j++)//辅助数组初始化
24         if(j!=k)
25         {
26             closedge[j].adjvex=k;
27             closedge[j].lowcost=map[k][j];
28         }
29     closedge[k].lowcost=0//初始,U={u}
30     int l=0;
31     for(i=1;i<n;i++)//选择其余n-1个顶点
32     {
33         double min=1000000;
34         for(j=1;j<=n;j++)//求出T的下一个结点:第k顶点
35             if(closedge[j].lowcost!=0&&min>closedge[j].lowcost)
36             {
37                 k=j;
38                 min=closedge[j].lowcost;
39             }
40         closedge[k].lowcost=0//第k顶点并入U集
41         d[l++]=map[k][closedge[k].adjvex]; //保存该边
42         for(j=1;j<=n;j++//新顶点并入U后重新选择最小边
43             if(map[k][j]<closedge[j].lowcost)
44             {
45                 closedge[j].adjvex=k;
46                 closedge[j].lowcost=map[k][j];
47             }
48     }
49 }
50 int main()
51 {
52     int t,m;
53     cin>>t;
54     while(t--)
55     {
56         cin>>m>>n;
57         for(i=1;i<=n;i++)
58             cin>>point[i].x>>point[i].y;
59         for(i=1;i<=n;i++//求出毎两个顶点之间的距离
60             for(j=1;j<i;j++)
61                 map[i][j]=map[j][i]=sqrt((point[i].x-point[j].x)*(point[i].x
62                 -point[j].x)+(point[i].y-point[j].y)*(point[i].y-point[j].y));
63         for(i=1;i<=n;i++)
64             map[i][i]=1000000;
65         prim(1);
66         sort(d,d+n-1,cmp); //把构成最小生成树的n-1条边从大到小排序
67         cout.setf(ios::fixed);//保留两位小数
68         cout.precision(2);
69         cout<<d[m-1]<<endl;//数组d从下标0开始存储,即第m条边
70     }
71     return 0;
72 }

 

 

posted @ 2011-08-24 19:58  笑巧  阅读(3128)  评论(0编辑  收藏  举报