(最小生成树+技巧)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 }