最小生成树的入门题,和普通裸题有些区别,需要做出一点修改
题目是要求两个岛的直接连线要大于等于10小于等于1000而不是说任意两个岛的路径和都是要满足这个条件,否则的话,要满足任意两个岛的路径和满足这个条件还是比较麻烦的
显然这道题用prim算法实现才好,因为最多有n*(n-1)/2条边用kruskal算法不好
在prim模板中要修改两个地方几个,一个是初始化
for(i=1; i<=n; i++)
{
adj[i]=1;
if(g[1][i]>=MIN) lowcoat[i]=g[1][i];
else lowcoat[i]=INF;
}
lowcoat[1]=0;
原本是直接lowcoat[i]=g[1][i]; 的。但是知道在prim算法中我们是不断更新lowcoat[i]使它的值不断变小的,所以lowcoat[i]只会越来越小,如果lowcoat[i]的值在初始化过程中就已经小于10,那么最后的构建结果中某条路径的长度一定小于10.
另外一个不同于模板的地方是
for(i=1; i<=n; i++)
if(lowcoat[i] && lowcoat[i]>g[k][i] && g[k][i]>=MIN)
{
lowcoat[i]=g[k][i];
adj[i]=k;
}
同样地,是为了避免在更新lowcoat[i]的时候使它的值小于10或大于1000,
for(sum=0,i=2; i<=n; i++)
{
if(g[i][adj[i]] < MIN || g[i][adj[i]]> MAX) { sum=-1; break;}
sum+=g[i][adj[i]];
}
这个就是最后的判断,判断所有n-1条连线,然后看每条连线是否满足条件,只要有一条连线不满足条件,就说明构建失败
而有些小细节还是可以修改一下的,更新部分可以改为
for(i=1; i<=n; i++)
if(lowcoat[i] && lowcoat[i]>g[k][i] && g[k][i]>=MIN)
{
lowcoat[i]=g[k][i];
adj[i]=k;
}
最后判断是否构建成功部分可以改为
for(sum=0,i=2; i<=n; i++)
{
if(g[i][adj[i]]> MAX) { sum=-1; break;}
sum+=g[i][adj[i]];
}
#include <stdio.h> #include <string.h> #include <math.h> #define N 110 #define MIN 10 #define MAX 1000 #define INF 982382334 int n; int x[N],y[N]; double g[N][N]; double dis(int i , int j) { return sqrt( 1.0*((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])) ); } void input() { int i,j; scanf("%d",&n); for(i=1; i<=n; i++) scanf("%d%d",&x[i],&y[i]); for(i=1; i<=n; i++) for(j=1 ;j<=n; j++) g[i][j]=g[j][i]=dis(i,j); return ; } void print_graph() { int i,j; for(i=1; i<=n; i++) { for(j=1; j<=n; j++) printf("%.1lf ",g[i][j]); printf("\n"); } } void prim() { double lowcoat[N],min,sum; int adj[N]; int v,i,j,k; for(i=1; i<=n; i++) { adj[i]=1; if(g[1][i]>=MIN) lowcoat[i]=g[1][i]; else lowcoat[i]=INF; } lowcoat[1]=0; for(v=1; v<n; v++) //还要纳入n-1个点 { min=INF; k=1; for(i=1; i<=n; i++) if(lowcoat[i] && lowcoat[i]<min) { min=lowcoat[i]; k=i;} lowcoat[k]=0; for(i=1; i<=n; i++) if(lowcoat[i] && lowcoat[i]>g[k][i] && g[k][i]>=MIN) { lowcoat[i]=g[k][i]; adj[i]=k; } } for(sum=0,i=2; i<=n; i++) { if(g[i][adj[i]] < MIN || g[i][adj[i]]> MAX) { sum=-1; break;} sum+=g[i][adj[i]]; } if(sum==-1) printf("oh!\n"); else { sum*=100; printf("%.1lf\n",sum); } return ; } int main() { int T; double ans; scanf("%d",&T); while(T--) { input(); // print_graph(); prim(); } return 0; }