畅通工程再续 Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u
Description
相信大家都听说一个“百岛湖”的地方吧,百岛湖的居民生活在不同的小岛中,当他们想去其他的小岛时都要通过划小船来实现。现在政府决定大力发展百岛湖,发 展首先要解决的问题当然是交通问题,政府决定实现百岛湖的全畅通!经过考察小组RPRush对百岛湖的情况充分了解后,决定在符合条件的小岛间建上桥,所 谓符合条件,就是2个小岛之间的距离不能小于10米,也不能大于1000米。当然,为了节省资金,只要求实现任意2个小岛之间有路通即可。其中桥的价格为 100元/米。
Input
输入包括多组数据。输入首先包括一个整数T(T <= 200),代表有T组数据。
每组数据首先是一个整数C(C <= 100),代表小岛的个数,接下来是C组坐标,代表每个小岛的坐标,这些坐标都是 0 <= x, y <= 1000的整数。
每组数据首先是一个整数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!
这一题醉醉的,题意很好懂,最小生成树,但是每个边权值必须在10~1000之内。否则就不能连,prim,kruscal都行。写之前一定要理好思路
#include<iostream> #include<cstring> #include<cmath> #include<cstdio> using namespace std; #define N 110 #define INF 0xfffffff struct node { int x, y; } P[N]; int vis[N]; double maps[N][N], dist[N]; void init() { for(int i = 0; i < N; i++) { vis[i] = 0; for(int j = 0; j < N; j++) { maps[i][j] = maps[j][i] = INF; } } } double prim(int n) { vis[0] = 1; dist[0] = 0; int cou = 1; double ans = 0; for(int i = 0; i < n; i++) dist[i] = maps[0][i]; for(int i = 0; i < n; i++) { int index, f; double Min = INF; index = f = 0; for(int j = 0; j < n; j++) { if(!vis[j] && dist[j] < Min) Min = dist[j], index = j, f = 1; // 如果边权值满足题意,并且该点没有连接的话,f置为1,就把该值用上联通该点 } if(f) { cou++; // cou计算已经被连接的点数,加一次边权值,联通点数加一 vis[index] = 1; ans += Min; } for(int j = 0; j < n; j++) { if(!vis[j] && dist[j] > maps[j][index]) dist[j] = maps[j][index]; // 最短路 } } if(cou != n) return -1; return ans; } int main() { int t, c; cin >> t; while(t--) { cin >> c; init(); for(int i = 0; i < c; i++) cin >> P[i].x >> P[i].y; for(int i = 0; i < c; i++) { for(int j = 0; j < c; j++) { int xx = P[i].x-P[j].x, yy = P[i].y-P[j].y; double q = sqrt(xx*xx+yy*yy); if(q >= 10 && q <= 1000) maps[i][j] = maps[j][i] = q; // 边权值即两点距离满足题意,就可以用,不然边权值就是INF,已初始化 } } double ans = prim(c); if(ans == -1) cout << "oh!" << endl; else printf("%.1f ", ans*100); } return 0; }
算法:Kruskal 和Prim 区别
* Kruskal:将所有边从小到大加入,在此过程中
判断是否构成回路
– 使用数据结构:并查集
– 时间复杂度:O(ElogE)
– 适用于稀疏图
* Prim:从任一节点出发,不断扩展
– 使用数据结构:堆
– 时间复杂度:O(ElogV) 或O(VlogV+E)(斐波那契堆)
– 适用于密集图
2
– 若不用堆则时间复杂度为O(V )