HDU1875+Prim模板
https://cn.vjudge.net/problem/HDU-1875
相信大家都听说一个“百岛湖”的地方吧,百岛湖的居民生活在不同的小岛中,当他们想去其他的小岛时都要通过划小船来实现。现在政府决定大力发展百岛湖,发展首先要解决的问题当然是交通问题,政府决定实现百岛湖的全畅通!经过考察小组RPRush对百岛湖的情况充分了解后,决定在符合条件的小岛间建上桥,所谓符合条件,就是2个小岛之间的距离不能小于10米,也不能大于1000米。当然,为了节省资金,只要求实现任意2个小岛之间有路通即可。其中桥的价格为 100元/米。
Input输入包括多组数据。输入首先包括一个整数T(T <= 200),代表有T组数据。
每组数据首先是一个整数C(C <= 100),代表小岛的个数,接下来是C组坐标,代表每个小岛的坐标,这些坐标都是 0 <= x, y <= 1000的整数。
Output每组输入数据输出一行,代表建桥的最小花费,结果保留一位小数。如果无法实现工程以达到全部畅通,输出”oh!”.Sample Input
2 2 10 10 20 20 3 1 1 2 2 1000 1000
Sample Output
1414.2 oh!
1 #include<iostream> 2 #include<stdio.h> 3 #include<bits/stdc++.h> 4 const int inf=999999999; 5 using namespace std; 6 int x[105],y[105]; 7 double w[105][105],dis[105]; 8 int n,m; 9 bool vis[105]; 10 double weight(int i,int j) 11 { 12 return sqrt(1.0*((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]))); 13 } 14 void prim() 15 { 16 int i,j,k; 17 bool flag=1; 18 double sum=0,tmp; 19 for(int i=1;i<=m;i++) 20 dis[i]=inf; 21 dis[1]=0; 22 for(i=1;i<=m;i++) 23 { 24 tmp=inf; 25 for(j=1;j<=m;j++) 26 if(!vis[j]&&tmp>dis[j]) 27 { 28 tmp=dis[j]; 29 k=j; 30 } 31 if(tmp==inf){flag=0;break;} 32 vis[k]=1; 33 sum+=tmp; 34 int y; 35 for(j=1;j<=m;j++) 36 { 37 if(!vis[j]&&dis[j]>w[k][j]) 38 dis[j]=w[k][j]; 39 } 40 41 } 42 if(flag) 43 printf("%.1f\n",sum*100); 44 else 45 printf("oh!\n"); 46 } 47 48 int main() 49 { 50 cin>>n; 51 for(int i=0;i<n;i++) 52 { 53 cin>>m; 54 memset(x,0,sizeof x); 55 memset(y,0,sizeof y); 56 memset(vis,0,sizeof vis); 57 for(int j=1;j<=m;j++) 58 cin>>x[j]>>y[j]; 59 for(int k=1;k<=m;k++) 60 for(int l=1;l<=m;l++) 61 { 62 double p=weight(k,l); 63 if(p>=10&&p<=1000) 64 w[k][l]=w[l][k]=p; 65 else 66 w[k][l]=w[l][k]=inf; 67 } 68 prim(); 69 } 70 return 0; 71 }
思路:
使用Prim求解最小生成树。
注意点:
1.一定要记得给每个数组初始化,一开始忘记给vis[]初始化了,导致调试了好久。
2.用memset的时候要注意类型,我给double赋极大值错误地使用了memset(dis,0x3f,sizeof dis);后来想到double类型是8个字节的,int是四个字节的(这是四字节赋极大值的方法,赋给8个字节的double类型的数得到的结果不一样),因为memset是按字节赋值的。这么给double赋值得到了一个约等于0的数,与预想的结果不同,导致错误。
Prim模板(解决最小生成树问题):
1 void prim() 2 { 3 int i,j,k,tmp; 4 memset(dis,0x3f,sizeof dis); 5 dis[1]=0; 6 for(i=1;i<=n;i++) 7 { 8 tmp=inf; 9 for(j=1;j<=n;j++) 10 if(!vis[j]&&tmp>dis[j]) 11 { 12 tmp=dis[j]; 13 k=j; 14 }//找到最小距离的节点 15 vis[k]=1; 16 for(j=1;j<=n;j++) 17 { 18 if(!vis[j]&&dis[j]>g[k][j]) 19 dis[j]=g[k][j]; 20 }//更新最短距离 21 } 22 }