题面挺绕的,“翻译”一下:
1.牧区是一个点,牧场是所有直接相连的点构成的联通块。
2.两个牧区之间的距离是这两个距离之间的最短路,只有直接相连的两个牧区之间的距离是欧几里得距离。
3.牧场的直径:这个牧场中两个相隔最远的两个牧区之间的距离。
4.求添加一条边合并两个牧场之后,使这个新的牧场的直径最小。
做法一步步想,就能想出来:
1.算出所有相邻牧区之间的距离,即边权。
2.用floyd求出所有牧区之间的最短路。
3.dfs联通块染色。
4.求出每一个牧场的直径。那么除了有一个M_blo[i]:代表牧场 i 的直径,还需要Max[i]:代表在一个联通块内,离牧区 i 最远的点的距离。然后用Max[i]更新M_blo[vis[i]]就行了。O(n2)枚举。
5.枚举点对(i, j),如果不在一个联通块内,就连边合并所在的两个牧场vis[i], vis[j],并用新的直径更新答案。新的直径可能是这三者中的最大值:1.vis[i]的直径。2.vis[j]的直径。3.Max[i] + dis[i][j] +Max[j]。还是O(n2)的。
所以最终复杂度是floyd复杂度,O(n3)。

1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<algorithm> 5 #include<cstring> 6 #include<cstdlib> 7 #include<cctype> 8 #include<vector> 9 #include<stack> 10 #include<queue> 11 using namespace std; 12 #define enter puts("") 13 #define space putchar(' ') 14 #define Mem(a, x) memset(a, x, sizeof(a)) 15 #define rg register 16 typedef long long ll; 17 typedef double db; 18 const db INF = 1e10; 19 const db eps = 1e-8; 20 const int maxn = 155; 21 inline ll read() 22 { 23 ll ans = 0; 24 char ch = getchar(), last = ' '; 25 while(!isdigit(ch)) last = ch, ch = getchar(); 26 while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar(); 27 if(last == '-') ans = -ans; 28 return ans; 29 } 30 inline void write(ll x) 31 { 32 if(x < 0) x = -x, putchar('-'); 33 if(x >= 10) write(x / 10); 34 putchar(x % 10 + '0'); 35 } 36 37 int n; 38 struct Node 39 { 40 int x, y; 41 }t[maxn]; 42 db dis[maxn][maxn]; 43 db Max[maxn], M_blo[maxn]; 44 45 db calc(Node a, Node b) 46 { 47 return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); 48 } 49 50 int vis[maxn], col = 0; 51 void dfs(int now) 52 { 53 vis[now] = col; 54 for(int i = 1; i <= n; ++i) 55 if(!vis[i] && dis[now][i] < INF) dfs(i); 56 } 57 58 int main() 59 { 60 n = read(); 61 for(int i = 1; i <= n; ++i) t[i].x = read(), t[i].y = read(); 62 for(int i = 1; i <= n; ++i) 63 { 64 for(int j = 1; j <= n; ++j) 65 { 66 int x; scanf("%1d", &x); 67 if(x || i == j) dis[i][j] = calc(t[i], t[j]); 68 else dis[i][j] = INF; 69 } 70 } 71 for(int i = 1; i <= n; ++i) if(!vis[i]) ++col, dfs(i); 72 for(int k = 1; k <= n; ++k) 73 for(int i = 1; i <= n; ++i) 74 for(int j = 1; j <= n; ++j) 75 dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]); 76 for(int i = 1; i <= n; ++i) 77 { 78 for(int j = 1; j <= n; ++j) 79 if(dis[i][j] < INF) Max[i] = max(Max[i], dis[i][j]); 80 M_blo[vis[i]] = max(M_blo[vis[i]], Max[i]); 81 } 82 db Mina = INF, Maxa = 0; 83 for(int i = 1; i <= n; ++i) 84 for(int j = i + 1; j <= n; ++j) if(vis[i] != vis[j]) 85 { 86 Maxa = max(max(M_blo[vis[i]], M_blo[vis[j]]), Max[i] + calc(t[i], t[j]) + Max[j]); 87 Mina = min(Mina, Maxa); 88 } 89 printf("%.6lf ", Mina); 90 return 0; 91 }