您的位置:首页 > 其它

poj1251------------------最小生成树(Prim)(a一送十)

2013-01-13 14:08 525 查看
第一次不用模板自己按理解写最小生成树。感觉很简单,但是真心被此题小陷阱恶心到了。

题是很简单,提交的时候无限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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: