Farmer John has a number of pastures on his farm. Cow paths connect some pastures with certain other pastures, forming a field. But, at the present time, you can find at least two pastures that cannot be connected by any sequence of cow paths, thus partitioning Farmer John's farm into multiple fields.
Farmer John would like add a single a cow path between one pair of pastures using the constraints below.
A field's `diameter' is defined to be the largest distance of all the shortest walks between any pair of pastures in the field. Consider the field below with five pastures, located at the points shown, and cow paths marked by lines:
15,15 20,15 D E *-------* | _/| | _/ | | _/ | |/ | *--------*-------* A B C 10,10 15,10 20,10
The `diameter' of this field is approximately 12.07106, since the longest of the set of shortest paths between pairs of pastures is the path from A to E (which includes the point set {A,B,E}). No other pair of pastures in this field is farther apart when connected by an optimal sequence of cow paths.
Suppose another field on the same plane is connected by cow paths as follows:
*F 30,15 / _/ _/ / *------ G H 25,10 30,10
In the scenario of just two fields on his farm, Farmer John would add a cow path between a point in each of these two fields (namely point sets {A,B,C,D,E} and {F,G,H}) so that the joined set of pastures {A,B,C,D,E,F,G,H} has the smallest possible diameter.
Note that cow paths do not connect just because they cross each other; they only connect at listed points.
The input contains the pastures, their locations, and a symmetric "adjacency" matrix that tells whether pastures are connected by cow paths. Pastures are not considered to be connected to themselves. Here's one annotated adjacency list for the pasture {A,B,C,D,E,F,G,H} as shown above:
A B C D E F G H A 0 1 0 0 0 0 0 0 B 1 0 1 1 1 0 0 0 C 0 1 0 0 1 0 0 0 D 0 1 0 0 1 0 0 0 E 0 1 1 1 0 0 0 0 F 0 0 0 0 0 0 1 0 G 0 0 0 0 0 1 0 1 H 0 0 0 0 0 0 1 0
Other equivalent adjacency lists might permute the rows and columns by using some order other than alphabetical to show the point connections. The input data contains no names for the points.
The input will contain at least two pastures that are not connected by any sequence of cow paths.
Find a way to connect exactly two pastures in the input with a cow path so that the new combined field has the smallest possible diameter of any possible pair of connected pastures. Output that smallest possible diameter.
Line 1: | An integer, N (1 <= N <= 150), the number of pastures |
Line 2-N+1: | Two integers, X and Y (0 <= X ,Y<= 100000), that denote that X,Y grid location of the pastures; all input pastures are unique. |
Line N+2-2*N+1: | lines, each containing N digits (0 or 1) that represent the adjacency matrix as described above, where the rows' and columns' indices are in order of the points just listed. |
8 10 10 15 10 20 10 15 15 20 15 30 15 25 10 30 10 01000000 10111000 01001000 01001000 01110000 00000010 00000101 00000010
The output consists of a single line with the diameter of the newly joined pastures. Print the answer to exactly six decimal places. Do not perform any special rounding on your output.
22.071068
吐槽:对此题的想法是这样的,先把所有的连通的两点之间的距离算出来,然后枚举两个不在同一连通块的两个点,在这两个点之间添加一条边,然后再进行floyd,求出直径。然后我就这样写了,果断超时了,然后才发现这个算法的时间复杂度为O(N^5),果断吐血啊。。。。还有就是把求直径放在求最短路的时候,这样也会错,因为在求最短路的时候,并不能保证两个点之间的距离是最短,因为还在动态更新。中间节点K的循环也必需写在最外层,不然也会错。
题解:先预先计算出所有连通的两点之间的距离,没连通则赋为无穷大,再进行floyd,之后求出最长直径来,然后计算出每个点以本身为起点的最长距离并用数组存储,假设是为数组名dis的一维数组。接下来就是枚举两个不在同一个连通块的点,假设为i和j。那么新直径的最小值为min(dis[i]+distance(i,j)+dis[j])。最后拿新直径和旧的最大直径比较,哪个大输出哪个。
1 /* 2 ID:spcjv51 3 PROG:cowtour 4 LANG:C 5 */ 6 #include<stdio.h> 7 #include<string.h> 8 #include<math.h> 9 #include<stdlib.h> 10 #define ZZ (1e10) 11 double distance[200][200],minnum,maxs,maxss,maxdia,dia[200]; 12 char graph[200][200]; 13 int x[200],y[200]; 14 int m,n; 15 16 17 double dis(int x1,int y1,int x2,int y2) 18 { 19 return(sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))); 20 } 21 void floyd() 22 { 23 int i,j,k; 24 for(k=1; k<=n; k++) 25 for(i=1; i<=n; i++) 26 for(j=1; j<=n; j++) 27 if(i!=j&&distance[i][k]+distance[k][j]<distance[i][j]) 28 distance[i][j]=distance[i][k]+distance[k][j]; 29 30 31 } 32 int main(void) 33 { 34 freopen("cowtour.in","r",stdin); 35 freopen("cowtour.out","w",stdout); 36 int i,j,l,r; 37 scanf("%d",&n); 38 minnum=10000; 39 for(i=1; i<=n; i++) 40 scanf("%d%d",&x[i],&y[i]); 41 for(i=1; i<=n; i++) 42 { 43 getchar(); 44 for(j=1; j<=n; j++) 45 scanf("%c",&graph[i][j]); 46 47 } 48 for(l=1; l<=n; l++) 49 for(r=1;r<=n;r++) 50 distance[l][r]=ZZ; 51 for(i=1; i<=n-1; i++) 52 for(j=i+1; j<=n; j++) 53 if(graph[i][j]=='1') 54 { 55 distance[i][j]=dis(x[i],y[i],x[j],y[j]); 56 distance[j][i]=distance[i][j]; 57 } 58 maxs=0; 59 floyd(); 60 for(i=1;i<=n;i++) 61 for(j=1;j<=n;j++) 62 if(i!=j&&distance[i][j]!=ZZ&&distance[i][j]>maxs) 63 maxs=distance[i][j]; 64 for(i=1;i<=n;i++) 65 { 66 maxdia=0; 67 for(j=1;j<=n;j++) 68 if(distance[i][j]!=ZZ&&distance[i][j]>maxdia) maxdia=distance[i][j]; 69 dia[i]=maxdia; 70 } 71 maxss=ZZ; 72 for(i=1;i<=n-1;i++) 73 for(j=i+1;j<=n;j++) 74 if(distance[i][j]==ZZ) 75 { 76 minnum=dia[i]+dia[j]+dis(x[i],y[i],x[j],y[j]); 77 if(minnum<maxss) 78 maxss=minnum; 79 } 80 if(maxss<maxs) 81 printf("%.6lf\n",maxs); 82 else 83 printf("%.6lf\n",maxss); 84 return 0; 85 }