【题目描述】
请编程找出一条连接两个不同牧场的路径,使得连上这条路径后,这个更大的新牧场有最小的直径。输出在所有牧场中最小的可能的直径。
【题目链接】
https://www.luogu.org/problemnew/show/P1522
【算法】
输出的解应当是(最大的原牧场直径)和 min(新生成的路径+新生成的路径两个端点延申出去的最长路径之和)的较大值。
枚举所有不连通的点计算两点之间距离和它们在原牧场中延申的最长路径(用到任意两点间最短距离,floyed)之和的最小值,最后和最大原牧场直径(最大延申路径)比较即可。
相同点间距离最好初始化为0。
【代码】
1 #include <bits/stdc++.h> 2 #define P pair<int,int> 3 using namespace std; 4 int n,i,j,k,tmp; 5 P p[200]; 6 double d[200][200],rec[200],ans=1e12,rm; 7 double calc(P p1,P p2) 8 { 9 return sqrt((p1.first-p2.first)*(p1.first-p2.first)+(p1.second-p2.second)*(p1.second-p2.second)); 10 } 11 int main() 12 { 13 scanf("%d",&n); 14 for(i=1;i<=n;i++) scanf("%d%d",&p[i].first,&p[i].second); 15 for(i=1;i<=n;i++) 16 for(j=1;j<=n;j++){ 17 scanf("%1d",&tmp); 18 if(tmp) d[i][j]=calc(p[i],p[j]); 19 else if(i!=j) d[i][j]=1e20; 20 } 21 for(k=1;k<=n;k++) { 22 for(i=1;i<=n;i++) 23 for(j=1;j<=n;j++) 24 d[i][j]=min(d[i][j],d[i][k]+d[k][j]); 25 } 26 for(i=1;i<=n;i++) { 27 for(j=1;j<=n;j++) 28 if(d[i][j]<1e7-1) rec[i]=max(rec[i],d[i][j]); 29 rm=max(rm,rec[i]); 30 } 31 for(i=1;i<=n;i++) 32 for(j=1;j<=n;j++) 33 if(d[i][j]>1e7-1) ans=min(ans,rec[i]+rec[j]+calc(p[i],p[j])); 34 ans=max(ans,rm); 35 printf("%.6f",ans); 36 return 0; 37 }