题目链接:https://www.luogu.org/problem/P1522
思路:编号,然后跑floyd,这是很清楚的。然后记录每个点在这个联通块中的最远距离。
然后分连通块,枚举两个点(不属于同一个连通块的)建边,计算可能的直径 dist[i] + dist[j] + dis(i,j)。
当然,这里有一个需要注意,(sccno[x]表示属于哪一个编号的连通块,sccdis[x]表示该连通块的直径),
在枚举点建边,形成新的牧场,得到新的可能的直径时,dist[i] + dist[j] + dis(i,j) >= max(sccdis[sccno[i]],sccdis[sccno[j]]),
这个是一定要成立的,因为新的可能的直径不可能小于sccdis[sccno[i]] 和 sccdis[sccno[j]](结合题目意思)。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <queue> 6 #include <map> 7 #include <cmath> 8 using namespace std; 9 10 typedef long long LL; 11 #define inf 1e11 12 #define rep(i, j, k) for (int i = (j); i <= (k); i++) 13 #define rep__(i, j, k) for (int i = (j); i < (k); i++) 14 #define per(i, j, k) for (int i = (j); i >= (k); i--) 15 #define per__(i, j, k) for (int i = (j); i > (k); i--) 16 17 const int N = 160; 18 int G[N][N]; 19 double f[N][N]; 20 double dist[N]; 21 int sccno[N]; 22 int scccnt; 23 double sccdis[N]; 24 int scct; 25 int head[N]; 26 int cnt; 27 int n; 28 29 struct node{ 30 double x,y; 31 }po[N]; 32 33 struct Edge{ 34 int to; 35 double w; 36 int next; 37 }e[N*N]; 38 39 void add(int u,int v,double w){ 40 e[cnt].to = v; 41 e[cnt].w = w; 42 e[cnt].next = head[u]; 43 head[u] = cnt++; 44 } 45 46 inline double dis(node& a,node& b){ 47 return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); 48 } 49 50 void dfs(int u){ 51 sccno[u] = scccnt; 52 for(int o = head[u]; ~o; o = e[o].next){ 53 int v = e[o].to; 54 if(!sccno[v]) dfs(v); 55 } 56 } 57 58 int main(){ 59 60 scanf("%d",&n); 61 62 //链式前向星 63 rep(i,1,n) head[i] = -1; 64 cnt = 0; 65 66 //距离矩阵初始化 67 rep(i,1,n) rep(j,1,n){ 68 if(i == j) f[i][j] = 0; 69 else f[i][j] = inf; 70 } 71 72 //点的输入 73 rep(i,1,n){ 74 scanf("%lf%lf",&po[i].x,&po[i].y); 75 } 76 77 //读图 78 rep(i,1,n){ 79 rep(j,1,n) scanf("%1d",&G[i][j]); 80 } 81 82 //建边 83 double way; 84 rep(i,1,n) rep(j,i+1,n){ 85 if(G[i][j]){ 86 way = dis(po[i],po[j]); 87 f[j][i] = f[i][j] = way; 88 add(i,j,way); 89 add(j,i,way); 90 } 91 } 92 93 //连通图 94 rep(i,1,n) if(!sccno[i]){ 95 ++scccnt; 96 dfs(i); 97 } 98 99 100 //最短路 101 rep(k,1,n) rep(i,1,n) rep(j,1,n){ 102 f[i][j] = min(f[i][j],f[i][k] + f[k][j]); 103 } 104 105 rep(i,1,n){ 106 rep(j,1,n){ 107 if(f[i][j] == inf) continue; 108 dist[i] = max(dist[i],f[i][j]); 109 } 110 } 111 112 //连通块最长直径 113 rep(i,1,n){ 114 sccdis[sccno[i]] = max(sccdis[sccno[i]],dist[i]); 115 } 116 117 double ans_1 = inf; 118 double tmp; 119 rep(i,1,n) rep(j,1,n){ 120 if(f[i][j] == inf){ 121 tmp = max(sccdis[sccno[i]],sccdis[sccno[j]]); 122 ans_1 = min(ans_1,dist[i] + dist[j] + dis(po[i],po[j])); 123 ans_1 = max(ans_1,tmp); 124 } 125 } 126 127 printf("%.6f ",ans_1); 128 129 getchar();getchar(); 130 return 0; 131 }