poj1251------------------最小生成树(Prim)(a一送十)
2013-01-13 14:08
525 查看
第一次不用模板自己按理解写最小生成树。感觉很简单,但是真心被此题小陷阱恶心到了。
题是很简单,提交的时候无限RE。
以为是数组越界了,改了之后还是RE。
看了一下discuss看到大神提醒RE是因为可能每组数据后面有好多空格。(太变态了)
所以scanf是用字符接收会出错。
两种解决办法:一种用cin输入。一种是用字符串接收。
2.
3.
4.
这个题要注意有重边。
另外,题上有说每条边最大值为1000000000,所以我用了long long型。
wa了很多次,最后一次wa是因为代码中间部分定义的
很难被发现,所以,以后还是在代码前段定义吧……
5.同上题
6.
用memset(low_dis, inf, sizeof(low_dis))时,其中的inf不可以太小,这道题我用时inf=100 001出现乱码,改为1 000 001结果才正确。
7.
8.
题意很难懂看懂,看了老半天词啊明白怎么回事,题之后就好写多了。
8.
wa了好多次。坐标村的时候用double存。我wa的原因竟然是inf定义的太小,没仔细看题啊。
10.
三维坐标里求,说的很玄乎,其实很简单。
11.
样例是错的!!!!巨坑爹!!
要求输出最小生成树的最大树边,最小生成树的树边个数,以及各个树边。wa无数,prime最简单三层循环 tle 一次。最后换了两层循环,ac。
题是很简单,提交的时候无限RE。
以为是数组越界了,改了之后还是RE。
看了一下discuss看到大神提醒RE是因为可能每组数据后面有好多空格。(太变态了)
所以scanf是用字符接收会出错。
两种解决办法:一种用cin输入。一种是用字符串接收。
#include<stdio.h> #define inf 100000 int a[110][110]; int vis[110]; int tree[110]; int main() { int n, t, w, sum; int cnt, min, min_pos; char ch[10]; while(scanf("%d", &n), n) { for(int i=0; i<n; i++) for(int j=0; j<n; j++) if(i == j) a[i][j]=0; else a[i][j] = inf; for(int i=0; i<n-1; i++) { scanf("%s%d", ch, &t); while(t--) { scanf("%s%d", ch, &w); a[i][ch[0]-'A'] = w; a[ch[0]-'A'][i] = w; } } sum = 0; cnt = 0; for(int i=0; i<n; i++) vis[i] = 0; tree[0] = 0; vis[cnt++] = 1; while(cnt < n) { min = inf; min_pos = n; for(int i=0; i<cnt; i++) { for(int j=0; j<n; j++) { if(a[tree[i]][j]<min && !vis[j]) { min = a[tree[i]][j]; min_pos = j; } } } sum += min; tree[cnt++] = min_pos; vis[min_pos] = 1; } printf("%d\n", sum); } return 0; }
2.
/*poj1287prim算法求最小生成树权值和*/ #include<stdio.h> #define inf 10000 int a[100][100]; int vis[100]; int tree[100]; int main() { int n, t, sum; int cnt, p, q, w, min, min_pos; while(scanf("%d", &n), n) { for(int i=0; i<n; i++) for(int j=0; j<n; j++) if(i == j) a[i][j] = 0; else a[i][j] = inf; scanf("%d", &t); while(t--) { scanf("%d %d %d", &p, &q, &w); if(w<a[p-1][q-1]) { a[p-1][q-1] = w; a[q-1][p-1] = w; } } for(int i=0; i<n; i++) vis[i] = 0; sum = 0; tree[0] = 0; cnt = 1; vis[0] = 1; while(cnt < n) { min = inf; min_pos = n; for(int i=0; i<cnt; i++) for(int j=0; j<n; j++) if(a[tree[i]][j]<min && !vis[j]) { min = a[tree[i]][j]; min_pos = j; } tree[cnt++] = min_pos; vis[min_pos] = 1; sum += min; } printf("%d\n", sum); } return 0; }
3.
/*poj1789prim算法求最小生成树权值和*/ #include<stdio.h> #include<string.h> #define inf 10000 char str[2010][10]; int a[2001][2001]; int vis[2001]; int tree[2001]; int main() { int n, w; int cnt, sum, min, min_pos; while(scanf("%d", &n), n) { for(int i=0; i<n; i++) scanf("%s", str[i]); for(int i=0; i<n; i++) for(int j=0; j<n; j++) if(i == j) a[i][j] = 0; else { int t = 0; for(int k=0; k<7; k++) if(str[i][k] != str[j][k]) t++; a[i][j] = t; a[j][i] = t; } for(int i=0; i<n; i++) vis[i] = 0; sum = 0; cnt = 1; vis[0] = 1; int low_dis[2001]; //各个点到其他点的最短路 int s = 0; memset(low_dis, inf, sizeof(low_dis)); while(cnt<n) { min = inf; for(int j=1; j<n; j++) { if(!vis[j] && a[s][j]<low_dis[j]) low_dis[j] = a[s][j]; if(!vis[j] && low_dis[j]<min) { min = low_dis[j]; min_pos = j; } } s = min_pos; vis[min_pos] = 1; sum += min; cnt++; } printf("The highest possible quality is 1/%d.\n", sum); } return 0; }
4.
这个题要注意有重边。
另外,题上有说每条边最大值为1000000000,所以我用了long long型。
wa了很多次,最后一次wa是因为代码中间部分定义的
long long low_dis[2001];
很难被发现,所以,以后还是在代码前段定义吧……
/*poj2395prim算法求最小生成树最大边*/ #include<stdio.h> #include<string.h> #define inf 1000000001 long long a[2001][2001]; int vis[2001]; int main() { int n, m, p, q; long long w, sum, min, max; int cnt, min_pos; while(scanf("%d %d", &n, &m) != EOF) { for(int i=0; i<n; i++) for(int j=0; j<n; j++) if(i == j) a[i][j] = 0; else a[i][j] = inf; while(m--) { scanf("%d %d %lld", &p, &q, &w); if(w < a[p-1][q-1]) { a[p-1][q-1] = w; a[q-1][p-1] = w; } } for(int i=0; i<n; i++) vis[i] = 0; sum = max = 0; cnt = 1; vis[0] = 1; long long low_dis[2001]; int s = 0; memset(low_dis, inf, sizeof(low_dis)); while(cnt<n) { min = inf; for(int j=1; j<n; j++) { if(!vis[j] && a[s][j]<low_dis[j]) low_dis[j] = a[s][j]; if(!vis[j] && low_dis[j]<min) { min = low_dis[j]; min_pos = j; } } if(min > max) max = min; s = min_pos; vis[min_pos] = 1; sum += min; cnt++; } printf("%lld\n", max); } return 0; }
5.同上题
/*poj2485prim算法求最小生成树最大边*/ #include<stdio.h> #include<string.h> #define inf 1000000001 long long a[501][501]; int vis[501]; int main() { int n, m; int sum, min, max; int cnt, min_pos; scanf("%d", &m); while(m--) { scanf("%d", &n); for(int i=0; i<n; i++) for(int j=0; j<n; j++) scanf("%d", &a[i][j]); for(int i=0; i<n; i++) vis[i] = 0; sum = max = 0; cnt = 1; vis[0] = 1; int low_dis[501]; int s = 0; memset(low_dis, inf, sizeof(low_dis)); while(cnt<n) { min = inf; for(int j=1; j<n; j++) { if(!vis[j] && a[s][j]<low_dis[j]) low_dis[j] = a[s][j]; if(!vis[j] && low_dis[j]<min) { min = low_dis[j]; min_pos = j; } } if(min > max) max = min; s = min_pos; vis[min_pos] = 1; sum += min; cnt++; } printf("%d\n", max); } return 0; }
6.
用memset(low_dis, inf, sizeof(low_dis))时,其中的inf不可以太小,这道题我用时inf=100 001出现乱码,改为1 000 001结果才正确。
/*poj1258prim算法求最小生成树权值和*/ #include<stdio.h> #include<string.h> #define inf 1000001 int a[101][101]; int vis[101]; int low_dis[101]; int main() { int n, sum, s; int min, min_pos, cnt; while(scanf("%d", &n) != EOF) { for(int i=0; i<n; i++) for(int j=0; j<n; j++) scanf("%d", &a[i][j]); for(int i=0; i<n; i++) vis[i] = 0; sum = 0; cnt = 1; s = 0; vis[0] = 1; memset(low_dis, inf, sizeof(low_dis)); while(cnt < n) { min = inf; for(int i=1; i<n; i++) { if(!vis[i] && a[s][i]<low_dis[i]) low_dis[i] = a[s][i]; if(!vis[i] && low_dis[i]<min) { min = low_dis[i]; min_pos = i; } } s = min_pos; vis[min_pos] = 1; cnt++; sum += min; } printf("%d\n", sum); } return 0; }
7.
/*poj2075prim算法求最小生成树权值和*/ #include<stdio.h> #include<string.h> char str[1100][21]; double a[1010][1010]; double vis[1010]; double low_dis[1010]; char tmp[21]; int main() { int n, s, t, cnt, min_pos, tp, tq; double sum, min, cable, inf=10001.0, w; char p[21], q[21]; scanf("%lf%d", &cable, &n); for(int i=0; i<n; i++) scanf("%s", str[i]); scanf("%d", &t); for(int i=0; i<n; i++) for(int j=0; j<n; j++) if(i == j) a[i][j] = 0.0; else a[i][j] = inf; while(t--) { scanf("%s %s", p, q); for(int j=0; j<n; j++) if(!strcmp(p, str[j])) { tp = j; } else if(!strcmp(q, str[j])) { tq = j; } scanf("%lf", &w); a[tp][tq] = w; a[tq][tp] = w; } for(int i=0; i<n; i++) vis[i] = 0; sum = 0; cnt = 1; s = 0; vis[0] = 1; for(int i=0; i<n; i++) low_dis[i]=inf; while(cnt < n) { min = inf; for(int i=1; i<n; i++) { if(!vis[i] && a[s][i]<low_dis[i]) low_dis[i] = a[s][i]; if(!vis[i] && low_dis[i]<min) { min = low_dis[i]; min_pos = i; } } s = min_pos; vis[min_pos] = 1; cnt++; sum += min; } if(cable - sum >= 0) printf("Need %.1lf miles of cable\n", sum); else printf("Not enough cable"); getchar(); getchar(); return 0; }
8.
题意很难懂看懂,看了老半天词啊明白怎么回事,题之后就好写多了。
/*poj2349prim算法求最小生成树第k大边*/ #include<stdio.h> #include<iostream> using namespace std; #include<string.h> #include<math.h> #include<stdlib.h> #include<algorithm> double a[501][501]; int vis[501]; double low_dis[501]; double ans[501]; int x[501], y[501]; int main() { int t, k, n, p, min_pos, cnt, s; double sum, min, inf = 100001.0; scanf("%d", &t); while(t--) { scanf("%d %d", &k, &n); for(int i=0; i<n; i++) scanf("%d %d", &x[i], &y[i]); for(int i=0; i<n; i++) for(int j=0; j<n; j++) if(i == j) a[i][j]=0.0; else a[i][j] = sqrt((double)((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]))); for(int i=0; i<n; i++) vis[i] = 0; sum = 0; cnt = 1; s = 0; vis[0] = 1; p = 0; for(int i=0; i<n; i++) low_dis[i]=inf; while(cnt < n) { min = inf; for(int i=1; i<n; i++) { if(!vis[i] && a[s][i]<low_dis[i]) low_dis[i] = a[s][i]; if(!vis[i] && low_dis[i]<min) { min = low_dis[i]; min_pos = i; } } s = min_pos; vis[min_pos] = 1; cnt++; ans[p++] = min; } sort(ans, ans+p); for(int i=0; i<p; i++) if(n-1-i == k) printf("%.2lf\n", ans[i]); } return 0; }
8.
wa了好多次。坐标村的时候用double存。我wa的原因竟然是inf定义的太小,没仔细看题啊。
/*poj3625prim算法求某些树边已知的最小生成树的其余树边之和*/ #include<stdio.h> #include<iostream> using namespace std; #include<string.h> #include<math.h> #include<stdlib.h> #include<algorithm> double a[1001][1001]; int vis[1001]; double low_dis[1001]; double x[1001], y[1001]; int main() { int t, k, n, p, min_pos, cnt, s, e, f; double sum, min, inf = 100000001.0; while(scanf("%d%d", &n, &t) != EOF) { for(int i=0; i<n; i++) scanf("%lf %lf", &x[i], &y[i]); for(int i=0; i<n; i++) for(int j=0; j<n; j++) if(i == j) a[i][j]=0.0; else a[i][j] = sqrt(((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]))+0.0); while(t--) { scanf("%d %d", &e, &f); a[e-1][f-1] = a[f-1][e-1] = 0.0; } for(int i=0; i<n; i++) vis[i] = 0; sum = 0; cnt = 1; s = 0; vis[0] = 1; p = 0; for(int i=0; i<n; i++) low_dis[i]=inf; while(cnt < n) { min = inf; for(int i=1; i<n; i++) { if(!vis[i] && a[s][i]<low_dis[i]) low_dis[i] = a[s][i]; if(!vis[i] && low_dis[i]<min) { min = low_dis[i]; min_pos = i; } } s = min_pos; vis[min_pos] = 1; cnt++; sum += min; } printf("%.2lf\n", sum); } return 0; }
10.
三维坐标里求,说的很玄乎,其实很简单。
/*poj2031prim算法求最小生成树权值之和*/ #include<stdio.h> #include<iostream> using namespace std; #include<string.h> #include<math.h> #include<stdlib.h> #include<algorithm> double a[101][101]; int vis[101]; double low_dis[101]; double x[101], y[101], z[101], r[101]; int main() { int t, k, n, p, min_pos, cnt, s, e, f; double sum, min, inf = 100000001.0, tmp; while(scanf("%d", &n), n) { for(int i=0; i<n; i++) scanf("%lf %lf %lf %lf", &x[i], &y[i], &z[i], &r[i]); for(int i=0; i<n; i++) for(int j=0; j<n; j++) if(i == j) a[i][j]=0.0; else { tmp = ( sqrt( (x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])+(z[i]-z[j])*(z[i]-z[j]) )-r[i]-r[j]); if(tmp>0) a[i][j] = tmp; else a[i][j] = 0.0; } for(int i=0; i<n; i++) vis[i] = 0; sum = 0.0; cnt = 1; s = 0; vis[0] = 1; for(int i=0; i<n; i++) low_dis[i]=inf; while(cnt < n) { min = inf; for(int i=1; i<n; i++) { if(!vis[i] && a[s][i]<low_dis[i]) low_dis[i] = a[s][i]; if(!vis[i] && low_dis[i]<min) { min = low_dis[i]; min_pos = i; } } s = min_pos; vis[min_pos] = 1; cnt++; sum += min; } printf("%.3lf\n", sum); } return 0; }
11.
样例是错的!!!!巨坑爹!!
要求输出最小生成树的最大树边,最小生成树的树边个数,以及各个树边。wa无数,prime最简单三层循环 tle 一次。最后换了两层循环,ac。
/*poj1861prim算法求最小生成树*/ #include<stdio.h> #include<string.h> #define inf 1000001 int a[1001][1001]; int vis[1001]; int x[1001], y[1001]; int tree[1001]; int main() { int n, t, w, p, q; int cnt, sum, min, min_posx, min_posy, max; while(scanf("%d %d", &n, &t) != EOF) { for(int i=0; i<n; i++) for(int j=0; j<n; j++) if(i == j) a[i][j] = 0; else a[i][j] = inf; while(t--) { scanf("%d %d %d", &p, &q, &w); if(w < a[p-1][q-1]) a[p-1][q-1] = a[q-1][p-1] = w; } for(int i=0; i<n; i++) vis[i] = 0; sum = 0; cnt = 1; int r=0; max = 0; vis[0] = 1; int low_dis[2001]; int low_dis_pos[2001]; int s = 0; memset(low_dis, inf, sizeof(low_dis)); while(cnt<n) { min = inf; for(int j=1; j<n; j++) { if(!vis[j] && a[s][j]<low_dis[j]) { low_dis[j] = a[s][j]; low_dis_pos[j] = s; } if(!vis[j] && low_dis[j]<min) { min = low_dis[j]; min_posx = low_dis_pos[j]; min_posy = j; } } s = min_posy; vis[min_posy] = 1; cnt++; x[r] = min_posx; y[r++] = min_posy; if(min > max) max = min; } printf("%d\n%d\n", max, r); for(int i=0; i<r; i++) printf("%d %d\n", x[i]+1, y[i]+1); } return 0; }
相关文章推荐
- HDU1301 POJ1251 Jungle Roads【Prim】【最小生成树】
- POJ1251 Jungle Roads 【最小生成树Prim】
- poj1251-prim最小生成树(dij改写)
- 最小生成树prim
- H - Highways(最小生成树prim)
- DS实验题 Floyd最短路径 & Prim最小生成树
- 最小生成树Prim
- hdu1102 Constructing Roads (最小生成树 prim 算法)
- 五、最小生成树之Kruskal和Prim
- 最小生成树 prim(与边无关,适合稠密的图,o(n^2))
- 最小生成树(prim)--poj2349
- 最小生成树Prim算法理解
- Prim最小生成树算法
- 最小树(一)(prim最小生成树)
- poj 题目1679 The Unique MST (最小生成树,次小生成树 prim)
- 【wikioi】1078最小生成树 prim 100分C源码
- poj 1258 prim最小生成树
- 无题 (最小生成树+prim)
- prim 求最小生成树(邻接矩阵)
- Agri-Net(最小生成树_prim||kruskral )