(最小生成树+技巧)POJ 3625 - Building Roads

题意:

平面上有很多点,有些点已经连了起来,现在想让你再连点,使得所有点连通,并且使新连接总距离最小。

 

分析:

显然最小生成树,但是不知道怎么处理已经连好的边。

看了别人的代码,才想到,直接把已经连好的边的花费赋为0不就行了。

因为你只需要弄出最小生成树,而已经在新增边的时候让已经连好的边优先选。

 

代码:

 

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <vector>
 5 #include <cmath>
 6 #include <iostream>
 7 
 8 using namespace std;
 9 
10 const int inf=0x3f3f3f3f;
11 const int maxn=1010;
12 
13 double x[maxn],y[maxn];
14 double cost[maxn][maxn];
15 double lowcost[maxn];
16 bool vis[maxn];
17 
18 
19 
20 double  dis(double x1,double y1,double x2,double y2) {
21     return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
22 }
23 
24 int n,m;
25 
26 int main() {
27 
28     while(~scanf("%d%d",&n,&m)) {
29         for(int i=0; i<n; i++) {
30             scanf("%lf%lf",&x[i],&y[i]);
31         }
32         for(int i=0; i<n; i++) {
33             for(int j=0; j<n; j++) {
34                 cost[i][j]=dis(x[i],y[i],x[j],y[j]);
35             }
36         }
37         for(int i=0; i<m; i++) {
38             int u,v;
39             scanf("%d%d",&u,&v);
40             u--,v--;
41             cost[u][v]=cost[v][u]=0;
42         }
43         memset(vis,false,sizeof(vis));
44         for(int i=1; i<n; i++)lowcost[i]=cost[0][i];
45         vis[0]=true;
46         double ans=0;
47         for(int i=1; i<n; i++) {
48             double minc = 1000000000.0;
49             int p=-1;
50             for(int j=0; j<n; j++) {
51                 if(!vis[j]&&lowcost[j]<minc) {
52                     minc=lowcost[j],p=j;
53                 }
54             }
55             ans+=minc;
56             vis[p]=true;
57             for(int j=0; j<n; j++) {
58                 if(!vis[j]&&lowcost[j]>cost[p][j]) {
59                     lowcost[j]=cost[p][j];
60                 }
61             }
62         }
63         printf("%.2f\n",ans);
64     }
65 
66     return 0;
67 
68 }

 

posted @ 2017-04-23 00:54  tak_fate  阅读(298)  评论(0编辑  收藏  举报