步骤是先求最小生成树,然后选两个不同的点,遍历所有的这样的点,选出两点人口比较大,而且连通两点的边的最大边比较大的情况。
因此要对i,j点连接起来的边进行遍历。
1 #include<stdio.h> 2 #include<string.h> 3 #include<math.h> 4 #define N 1010 5 #define max(a,b) ((a)>(b)?(a):(b)) 6 #define INF 999999999 7 8 double map[N][N],lowcost[N],cost[N][N]; 9 int vis[N];/*-1表示该点已经加入,非0表示i和vis[i]的值表示的点构成一条短边*/ 10 int n; 11 typedef struct 12 { 13 double x,y,w; 14 } Point; 15 Point point[N]; 16 17 double dis(Point a,Point b) 18 { 19 return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); 20 } 21 22 void input(void) 23 { 24 int i,j; 25 scanf("%d",&n); 26 for(i=0; i<n; i++) 27 scanf("%lf%lf%lf",&point[i].x,&point[i].y,&point[i].w); 28 for(i=0; i<n-1; i++) 29 for(j=i+1; j<n; j++) 30 map[i][j]=map[j][i]=dis(point[i],point[j]); 31 } 32 33 double prim(void) 34 { 35 memset(cost,0,sizeof(cost)); 36 memset(vis,0,sizeof(vis)); 37 double ans=0; 38 int e=0,i,j;/*e=0表示首先将点0加入集合U*/ 39 vis[0]=-1;/*e用来记录新加入的顶点*/ 40 for(i=0; i<n; i++) 41 lowcost[i]=1.0*INF; 42 for(i=0; i<n-1; i++) 43 { 44 double micost=1.0*INF; 45 int miedge=-1; 46 for(j=1; j<n; j++) 47 if(vis[j]!=-1) 48 { 49 double temp=map[e][j]; 50 if(temp<lowcost[j]) 51 { 52 lowcost[j]=temp; 53 vis[j]=e; 54 } 55 if(lowcost[j]<micost) 56 micost=lowcost[miedge=j]; 57 } 58 ans+=micost; 59 cost[miedge][vis[miedge]]=cost[vis[miedge]][miedge]=map[vis[miedge]][miedge]; 60 for(j=0; j<n; j++) 61 if(vis[j]==-1) 62 cost[j][miedge]=cost[miedge][j]=max(cost[miedge][vis[miedge]],cost[j][vis[miedge]]); 63 vis[e=miedge]=-1; 64 } 65 return ans; 66 } 67 68 void solve(void) 69 { 70 int i,j; 71 double mst=prim(); 72 /* printf("%f ",mst);*/ 73 double ans=-1; 74 for(i=0; i<n-1; i++) 75 for(j=i+1; j<n; j++) 76 { 77 double t=(point[i].w+point[j].w)/(mst-cost[i][j]); 78 ans=max(ans,t); 79 } 80 printf("%.2f ",ans); 81 } 82 83 int main(void) 84 { 85 int t; 86 scanf("%d",&t); 87 while(t--) 88 { 89 input(); 90 solve(); 91 } 92 return 0; 93 }