zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    致初学作曲的业余音乐爱好者 (转载)
    OpenGL教程 "Top Ten" (转载)
    开发者:我们应该在哪个层次编写代码?
    计算机科学数学理论浅谈 (转载)
    fltk2更新简介
    搜集的优良OpenGL教程 (转载)
    [转载] 跨平台C++程序开发系列文章
    通过HtppWebRequest发送图片到服务器并保存
    技术之外
    Hibernate写查询语句注意事项
  • 原文地址:https://www.cnblogs.com/mrclr/p/9879360.html
Copyright © 2011-2022 走看看