畅通工程再续 HDU - 1875 最小生成树之Kruskal算法
相信大家都听说一个“百岛湖”的地方吧,百岛湖的居民生活在不同的小岛中,当他们想去其他的小岛时都要通过划小船来实现。现在政府决定大力发展百岛湖,发展首先要解决的问题当然是交通问题,政府决定实现百岛湖的全畅通!经过考察小组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 <cstdio> 2 #include <fstream> 3 #include <algorithm> 4 #include <cmath> 5 #include <deque> 6 #include <vector> 7 #include <queue> 8 #include <string> 9 #include <cstring> 10 #include <map> 11 #include <stack> 12 #include <set> 13 #include <sstream> 14 #include <iostream> 15 #define mod 998244353 16 #define eps 1e-6 17 #define ll long long 18 #define INF 0x3f3f3f3f 19 using namespace std; 20 //u表示起点,v表示终点,cost表示花费 21 struct node 22 { 23 int u,v; 24 double cost; 25 bool operator < (const node & p) const { 26 return cost < p.cost; 27 } 28 }; 29 //存放边的信息 30 vector<node> ve; 31 int n; 32 //fa表示当前i的最远祖先 33 int fa[110]; 34 //初始化fa,开始时自己是自己的祖先 35 void init(int qwq) 36 { 37 for(int i=0;i<=qwq;i++) 38 { 39 fa[i]=i; 40 } 41 } 42 //查找最远祖先,同时进行路径压缩 43 int find(int x) 44 { 45 if(fa[x]==x) 46 { 47 return x; 48 } 49 return fa[x]=find(fa[x]); 50 } 51 //判断最远祖先是否相同 52 bool che(int x,int y) 53 { 54 return find(x)==find(y); 55 } 56 //合并x,y,把他们放到同一个家族中 57 void mer(int x,int y) 58 { 59 if(!che(x,y)) 60 { 61 fa[fa[x]]=fa[y]; 62 } 63 return ; 64 } 65 //保存点的信息 66 struct dian 67 { 68 int x,y; 69 }; 70 dian di[105]; 71 //求点与点之间的距离 72 double distan(dian a,dian b) 73 { 74 return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); 75 } 76 77 int main() 78 { 79 scanf("%d",&n); 80 while(n--) 81 { 82 int m; 83 scanf("%d",&m); 84 //初始化 85 init(m); 86 for(int i=0;i<m;i++) 87 { 88 scanf("%d %d",&di[i].x,&di[i].y); 89 } 90 node no; 91 //将点的坐标转换成点与点之间的距离并存入容器中 92 for(int i=0;i<m-1;i++) 93 { 94 for(int j=i+1;j<m;j++) 95 { 96 no.u=i; 97 no.v=j; 98 no.cost=distan(di[i],di[j]); 99 ve.push_back(no); 100 } 101 } 102 //排序 103 sort(ve.begin(),ve.end()); 104 //ans表示树上边的权值总和 105 double ans=0; 106 //js表示连接的边数 107 int js=0; 108 for(int i=0;i<ve.size();i++) 109 { 110 //但两个点不在一个集合中且这两个点之间的距离能够建桥时连接他们 111 if(!che(ve[i].u,ve[i].v)&&ve[i].cost>=10&&ve[i].cost<=1000) 112 { 113 mer(ve[i].u,ve[i].v); 114 ans+=ve[i].cost; 115 js++; 116 } 117 //如果连接了m-1条边则所有的点都已经连载一起了,不需要再循环了 118 if(js==m-1) 119 { 120 break; 121 } 122 } 123 //如果连接了m-1条边则表示所有的点已连接否则无法全部畅通 124 if(js==m-1) 125 { 126 printf("%.1lf\n",ans*100); 127 } 128 else 129 { 130 printf("oh!\n"); 131 } 132 //清除容器的内存 133 ve.clear(); 134 } 135 }