luogu1522 牛的旅行
题目大意
每个牧场里的某些坐标位置有牧区,牧区间有一个个路径(长度为位置间的直线距离)。一个连通块内两个节点间的最短路径长度最大值为它的直径。请编程找出一条连接两个不同牧场的路径,使得连上这条路径后,这个更大的新牧场有最小的直径。输出在所有牧场中最小的可能的直径。
思路
注意
Floyd先枚举k。
#include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <vector> #include <cassert> using namespace std; const int MAX_NODE = 200; const double INF = 200000; double Dist[MAX_NODE][MAX_NODE]; int TotNode, TotBlock; struct Coor//Coordinate { int X, Y; double Dist(const Coor& a)const { double x1 = X, y1 = Y, x2 = a.X, y2 = a.Y; double dx = abs(x1 - x2), dy = abs(y1 - y2); return sqrt(dx * dx + dy * dy); } }; struct Node { Coor Coordinate; double MaxDist; }_nodes[MAX_NODE]; void InitDist() { for (int i = 0; i < MAX_NODE; i++) for (int j = 0; j < MAX_NODE; j++) Dist[i][j] = INF; for (int i = 0; i < MAX_NODE; i++) Dist[i][i] = 0; } void Read() { scanf("%d", &TotNode); for (int i = 1; i <= TotNode; i++) scanf("%d%d\n", &_nodes[i].Coordinate.X, &_nodes[i].Coordinate.Y); char s[MAX_NODE]; for (int i = 1; i <= TotNode; i++) { scanf("%s", s + 1); for (int j = 1; j <= TotNode; j++) if (s[j] - '0') Dist[i][j] = _nodes[i].Coordinate.Dist(_nodes[j].Coordinate); } } void Floyd() { for (int k = 1; k <= TotNode; k++) for (int i = 1; i <= TotNode; i++) for (int j = 1; j <= TotNode; j++) Dist[i][j] = min(Dist[i][j], Dist[i][k] + Dist[k][j]); } double MaxMaxDist; void GetNodeMaxDist() { for (int i = 1; i <= TotNode; i++) for (int j = 1; j <= TotNode; j++) if (Dist[i][j] < INF) { _nodes[i].MaxDist = max(_nodes[i].MaxDist, Dist[i][j]); MaxMaxDist = max(MaxMaxDist, _nodes[i].MaxDist); } } double GetAns() { double ans = INF; for (int i = 1; i <= TotNode; i++) for (int j = 1; j <= TotNode; j++) if (Dist[i][j] == INF) ans = min(ans, _nodes[i].MaxDist + _nodes[j].MaxDist + _nodes[i].Coordinate.Dist(_nodes[j].Coordinate)); return max(ans, MaxMaxDist); } int main() { InitDist(); Read(); Floyd(); GetNodeMaxDist(); printf("%.6f\n", GetAns()); return 0; }