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  }

 

 

你可能感兴趣的:(最小生成树)