Problem
题目简述
给你两个独立的联通块,求:在两个联通块上各找一个点连起来,使得新的联通块的直径的最小值。
思路
本题主要做法:\(Floyd\)。
- 首先,Floyd求出任意两个点之间的最短路。
- 枚举每一个点,求出以这个点能走到的所有点中距离的最大值。(一定在能走到的情况下,不然默认距离就是0x3f, 会导致结果错误 )
- 设 \(ma1\) 为最大的直径(每个 \(ma[i]\) 的最大值)。
- 再设 \(mi1\) 为任意两点加边的新直径的最小值。
- 答案为:\(max(ma1, mi1)\) 。
代码
#include <iostream>
#define ll long long
using namespace std;
const int N = 160, INF = 0x3f3f3f3f;
double d[N][N], ma1, mi1, ma[N];
ll p[N][3];
ll pf(int x) { return 1LL * x * x; }
double get(int t1, int t2) {
return sqrt(pf(p[t1][1] - p[t2][1]) + pf(p[t1][2] - p[t2][2]));
}
int n;
char c;
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> p[i][1] >> p[i][2];
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
cin >> c;
if (i == j) d[i][j] = 0;
else if (c == '1') d[i][j] = get(i, j);
else d[i][j] = INF;
}
}
for (int k = 1; k <= n; k++) {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
}
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (d[i][j] != INF) ma[i] = max(ma[i], d[i][j]);
}
ma1 = max(ma1, ma[i]);
}
mi1 = INF;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (d[i][j] == INF) mi1 = min(mi1, ma[i] + ma[j] + get(i, j));
}
}
printf("%.6lf", max(ma1, mi1));
return 0;
}
标签:ma1,Cow,pf,int,ll,t2,t1,Tours,USACO2.4
From: https://www.cnblogs.com/yhx0322/p/17739244.html