题目大意
给出n个牛舍的坐标x,y。一个牧场的直径就是牧场中最远的两个牧区的距离(简单的说就是从每个点出发最远的那个点的距离所以不能刻意绕远路)
问能否加一条边,使图中最大的路径变小
思考
一开始以为最远的最短距离二分一下就可以了,但是无从下手。
后面想到可以 先求一波最短路径,然后把每个点到其他点的最长距离储存起来记作mm[],再模拟加边,储存加边后最小的那个直径记作Min。
最后把Min与 mm[] 比较,将最大的保留输出。
#include <cstdio> #include <cmath> #include <algorithm> using namespace std; const int maxn = 160; const int INF = 1e8; int n,x[maxn],y[maxn]; double MIN=1000000,G[maxn][maxn],mm[maxn]; double Length(int i,int j){ return sqrt( (x[i]-x[j])*(x[i]-x[j]) + (y[i]-y[j]) * (y[i]-y[j]) ); } void floyd(){ for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++){ if( ( G[i][k]+G[k][j]<G[i][j] ) && (i!=j) && (j!=k) && (i!=k)) G[i][j]=G[i][k]+G[k][j]; } } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d%d",&x[i],&y[i]); } for(int i=1;i<=n;i++) { char fuck[233]; scanf("%s",fuck+1); for(int j=1;j<=n;j++){ fuck[j] = fuck[j] - '0'; if(fuck[j]==1){ G[i][j] = Length(i,j); } else{ if(i!=j) G[i][j] = INF; } } } floyd(); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++){ if( (G[i][j]>mm[i]) && (G[i][j]!=INF)) mm[i] = G[i][j]; } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++){ if(G[i][j]==INF){ MIN = min(MIN,Length(i,j)+mm[i]+mm[j]); } } for(int i=1;i<=n;i++) MIN = max(mm[i],MIN); printf("%.6lf\n",MIN); return 0; }