luogu P1522 Cow Tours

嘟嘟嘟

题面挺绕的,“翻译”一下:

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 }
View Code
原文地址:https://www.cnblogs.com/mrclr/p/9879360.html