1 条题解
-
0
难点主要在读题上,要分清楚什么是牧区、什么是牧场、什么是大牧场。
最短路的部分用floyd比较方便快捷。也可以用floyd的答案判断两个点是否相连。
特别需要注意可能会出现直径不经过新加入的边的情况。
#include <bits/stdc++.h> using namespace std; const int MAXN = 150; const double INF = 200000 * 150; int n, m, s, t; int x[MAXN + 5], y[MAXN + 5]; double dis[MAXN + 5][MAXN + 5]; double len(int u, int v) { return sqrt((long long)(x[u] - x[v]) * (x[u] - x[v]) + (long long)(y[u] - y[v]) * (y[u] - y[v])); } double maxLen[MAXN]; // maxLen[i]: 到i号点距离最远的点的距离 signed main() { ios::sync_with_stdio(false); cin.tie(0); // 输入 cin >> n; for (int i = 1; i <= n; i++) cin >> x[i] >> y[i]; for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) dis[i][j] = INF; dis[i][i] = 0; } for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) { char now; cin >> now; // 牧区 i 与牧区 j 的连接关系是 now if (now == '1') { dis[i][j] = len(i, j); } } // floyd for (int k = 1; k <= n; k++) for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]); // 预处理距离每个点最远的点的距离 for (int i = 1; i <= n; i++) { maxLen[i] = 0; for (int j = 1; j <= n; j++) { // double类型直接比较相等可能会有问题 // 下面的式子逻辑上等价于 dis[i][j]!=INF if (abs(dis[i][j] - INF) > 1e-12) { maxLen[i] = max(maxLen[i], dis[i][j]); } } } // 枚举可能的答案 double ans = INF; for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { // 如果 i,j 属于不同的牧场,尝试加一条边沟通两个牧场 if (abs(dis[i][j] - INF) < 1e-12) { if (maxLen[i] + maxLen[j] + len(i, j) < ans) { ans = maxLen[i] + maxLen[j] + len(i, j); } } } } // 有没有可能还不如原来的直径大 for (int i = 1; i <= n; i++) ans = max(ans, maxLen[i]); // 输出 cout << fixed << setprecision(6) << ans << "\n"; return 0; }
- 1
信息
- ID
- 562
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- 6
- 标签
- (无)
- 递交数
- 26
- 已通过
- 11
- 上传者