HDU1875 畅通工程再续 【最小生成树Prim】
2014-07-29 15:28
337 查看
畅通工程再续
[b]Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 14590 Accepted Submission(s): 4497
[/b]
[align=left]Problem Description[/align]
相信大家都听说一个“百岛湖”的地方吧,百岛湖的居民生活在不同的小岛中,当他们想去其他的小岛时都要通过划小船来实现。现在政府决定大力发展百岛湖,发展首先要解决的问题当然是交通问题,政府决定实现百岛湖的全畅通!经过考察小组RPRush对百岛湖的情况充分了解后,决定在符合条件的小岛间建上桥,所谓符合条件,就是2个小岛之间的距离不能小于10米,也不能大于1000米。当然,为了节省资金,只要求实现任意2个小岛之间有路通即可。其中桥的价格为 100元/米。
[align=left]Input[/align]
输入包括多组数据。输入首先包括一个整数T(T <= 200),代表有T组数据。
每组数据首先是一个整数C(C <= 100),代表小岛的个数,接下来是C组坐标,代表每个小岛的坐标,这些坐标都是 0 <= x, y <= 1000的整数。
[align=left]Output[/align]
每组输入数据输出一行,代表建桥的最小花费,结果保留一位小数。如果无法实现工程以达到全部畅通,输出”oh!”.
[align=left]Sample Input[/align]
2
2
10 10
20 20
3
1 1
2 2
1000 1000
[align=left]Sample Output[/align]
1414.2
oh!
这题的陷阱是注意浮点数。
2014.8.17更新:31ms prim
#include <stdio.h> #include <string.h> #include <math.h> #define maxn 102 #define maxm (maxn * maxn) >> 1 #define inf 0x3f3f3f3f struct Node2{ int x, y; } V[maxn]; struct Node{ int u, v; double d; } E[maxm]; double ans, dist[maxn], map[maxn][maxn]; bool vis[maxn]; double calDist(int i, int j) { double x = V[i].x - V[j].x; double y = V[i].y - V[j].y; return sqrt(x * x + y * y); } int getNext(int n) { int u = -1, i; double tmp = inf; for(i = 1; i <= n; ++i) if(!vis[i] && dist[i] < tmp){ tmp = dist[i]; u = i; } return u; } bool Prim(int n) { int i, u, v, count = 0; double tmp; ans = 0.0; for(i = 1; i <= n; ++i){ vis[i] = 0; dist[i] = inf; if(map[1][i] >= 10.0 && map[1][i] <= 1000.0) dist[i] = map[1][i]; } u = 1; dist[u] = 0.0; vis[u] = 1; u = getNext(n); while(count < n - 1){ if(u == -1) return false; vis[u] = 1; ans += dist[u]; ++count; for(i = 1; i <= n; ++i) if(!vis[i] && map[u][i] <= 1000.0 && map[u][i] >= 10.0 && dist[i] > map[u][i]){ dist[i] = map[u][i]; } u = getNext(n); } return true; } int main() { int t, n, i, j; scanf("%d", &t); while(t--){ scanf("%d", &n); for(i = 1; i <= n; ++i) scanf("%d%d", &V[i].x, &V[i].y); for(i = 1; i < n; ++i) for(j = i + 1; j <= n; ++j) map[i][j] = map[j][i] = calDist(i, j); if(!Prim(n)) printf("oh!\n"); else printf("%.1lf\n", ans * 100.0); } }
Kruskal:140ms
#include <stdio.h> #include <string.h> #include <algorithm> #include <math.h> #define maxn 102 #define maxm (maxn * maxn) >> 1 using std::sort; int pre[maxn], count, id; struct Node2{ int x, y; } V[maxn]; struct Node{ int u, v; double d; } E[maxm]; double ans; int ufind(int k) { int a = k, b; while(pre[k] != -1) k = pre[k]; while(a != k){ b = pre[a]; pre[a] = k; a = b; } return k; } bool cmp(Node a, Node b){ return a.d < b.d; } double calDist(int i, int j) { double x = V[i].x - V[j].x; double y = V[i].y - V[j].y; return sqrt(x * x + y * y); } bool Kruskal(int n, int m) { ans = 0; int i, u, v; for(i = 0; i < m; ++i){ u = ufind(E[i].u); v = ufind(E[i].v); if(u != v && E[i].d >= 10 && E[i].d <= 1000){ ans += E[i].d; pre[v] = u; if(--count == 1) return true; } } return 1 == count; } int main() { int t, n, i, j; scanf("%d", &t); while(t--){ memset(pre, -1, sizeof(pre)); scanf("%d", &n); count = n; for(i = 1; i <= n; ++i) scanf("%d%d", &V[i].x, &V[i].y); for(i = 1, id = 0; i < n; ++i) for(j = i + 1; j <= n; ++j){ E[id].u = i; E[id].v = j; E[id++].d = calDist(i, j); } sort(E, E + id, cmp); if(!Kruskal(n, id)) printf("oh!\n"); else printf("%.1lf\n", ans * 100.0); } }
更新前: 328ms Prim
#include <stdio.h> #include <string.h> #include <math.h> #define maxn 102 double map[maxn][maxn]; bool vis[maxn]; struct Node{ int x, y; } arr[maxn]; double cal(Node a, Node b) { double x = a.x - b.x, y = a.y - b.y; return sqrt(x * x + y * y); } void Prim(int n) { int u, i, j, count = 0; double len = 0, tmp; vis[0] = 1; while(count < n - 1){ for(i = 0, tmp = -1; i < n; ++i){ if(!vis[i]) continue; for(j = 0; j < n; ++j){ if(map[i][j] >= 0 && !vis[j] && (map[i][j] < tmp || tmp < 0)){ tmp = map[i][j]; u = j; } } } if(tmp > 0){ ++count; vis[u] = 1; len += tmp * 100; }else break; } if(count == n - 1) printf("%.1lf\n", len); else printf("oh!\n"); } int main() { //freopen("in.txt", "r", stdin); //freopen("out.txt", "w", stdout); int t, n, a, b, i, j; double len; scanf("%d", &t); while(t--){ scanf("%d", &n); memset(vis, 0, sizeof(vis)); for(i = 0; i <= n; ++i) for(j = 0; j <= n; ++j) map[i][j] = -1; for(i = 0; i < n; ++i){ scanf("%d%d", &arr[i].x, &arr[i].y); for(j = 0; j < i; ++j){ len = cal(arr[i], arr[j]); if(len >= 10.0 && len <= 1000.0){ if(map[i][j] < 0 || len < map[i][j]) map[i][j] = map[j][i] = len; } } } Prim(n); } return 0; }
相关文章推荐
- hdu1875 畅通工程再续 (最小生成树之prim 算法)
- HDU1875 畅通工程再续(最小生成树,Prim,kruskal算法)
- 最小生成树 Prim hdu1875 畅通工程再续
- HDU1863 - 畅通工程 Prim最小生成树算法
- 8-06. 畅通工程之局部最小花费问题(35)(最小生成树_Prim)(ZJU_PAT)
- hdu1875 畅通工程再续 (KRUSKAL求最小生成树)
- HDUOJ_1863(畅通工程) (最小生成树)(prim和克鲁斯卡尔两种方法解)
- hdu1863 畅通工程(最小生成树之prim)
- HDU 1863 畅通工程(prim最小生成树)
- HDU 1875 畅通工程再续 (prim最小生成树)
- 最小生成树(kruskal&prim)畅通工程
- HDOJ 1879 继续畅通工程 最小生成树 kruskal && prim
- hdu 1879 继续畅通工程(最小生成树,prim)
- hdu 1233 还是畅通工程--最小生成树prim
- HDU 1862 畅通工程(最小生成树prim)
- 【最小生成树+Prim】杭电 hdu 1875 畅通工程再续
- HDU1879 继续畅通工程 【最小生成树Prim】
- hdu1233还是畅通工程 最小生成树(prim或kruskal)
- hdoj 1875 畅通工程再续【最小生成树 kruskal && prim】
- HDU 1863 畅通工程 (最小生成树--Kruscal、Prim)