• P1522 牛的旅行


    P1522 牛的旅行 Cow Tours

    提交 11.44k
    通过 4.97k
    时间限制 1.00s
    内存限制 125.00MB
    题目提供者 洛谷
    历史分数100

    提交记录

    标签

     
    查看算法标签
    进入讨论版

    相关讨论

     
    查看讨论

    推荐题目

     
    查看推荐
     

    展开

    题目描述

    Farmer John 的农场里有很多牧区。有的路径连接一些特定的牧区。一片所有连通的牧区称为一个牧场。但是就目前而言,你能看到至少有两个牧区通过任何路径都不连通。这样,Farmer John 就有多个牧场了。

    John 想在牧场里添加恰好一条路径。对这条路径有以下限制:

    一个牧场的直径就是牧场中最远的两个牧区的距离(本题中所提到的所有距离指的都是最短的距离)。考虑如下的有5个牧区的牧场,牧区用 * 表示,路径用直线表示。每一个牧区都有自己的坐标:

                    (15,15) (20,15)
                     D       E
                     *-------*
                     |     _/|
                     |   _/  |
                     | _/    |
                     |/      |
            *--------*-------*
            A        B       C
         (10,10)  (15,10) (20,10)
    

    这个牧场的直径大约是 12.0710612.0710612.07106,最远的两个牧区是 A 和 E,它们之间的最短路径是 A→B→EA o B o EABE。

    这里是另一个牧场:

                             *F(30,15)
                            / 
                          _/  
                        _/    
                       /      
                      *------* 
                      G      H
                      (25,10)   (30,10)
    

    在目前的情景中,他刚好有两个牧场。John 将会在两个牧场中各选一个牧区,然后用一条路径连起来,使得连通后这个新的更大的牧场有最小的直径。

    注意,如果两条路径中途相交,我们不认为它们是连通的。只有两条路径在同一个牧区相交,我们才认为它们是连通的。

    输入文件包括牧区、它们各自的坐标,还有一个如下的对称邻接矩阵:

    :
      A  B  C  D  E  F  G  H 
    A  0  1  0  0  0  0  0  0
    B  1  0  1  1  1  0  0  0
    C  0  1  0  0  1  0  0  0
    D  0  1  0  0  1  0  0  0
    E  0  1  1  1  0  0  0  0
    F  0  0  0  0  0  0  1  0
    G  0  0  0  0  0  1  0  1
    H  0  0  0  0  0  0  1  0
    

    其他邻接表中可能直接使用行列而不使用字母来表示每一个牧区。输入数据中不包括牧区的名字。

    输入文件至少包括两个不连通的牧区。

    请编程找出一条连接两个不同牧场的路径,使得连上这条路径后,这个更大的新牧场有最小的直径。输出在所有牧场中最小的可能的直径。


    输出格式

    只有一行,包括一个实数,表示所求直径。数字保留六位小数。

    只需要打到小数点后六位即可,不要做任何特别的四舍五入处理。

    输入输出样例

    输入 #1
    8
    10 10
    15 10
    20 10
    15 15
    20 15
    30 15
    25 10
    30 10
    01000000
    10111000
    01001000
    01001000
    01110000
    00000010
    00000101
    00000010
    输出 #1
    22.071068
    

    说明/提示

    翻译来自NOCOW

    USACO 2.4

    思路

      因为给出了连通块编号,所以可以直接处理出每个连通块内的最远距离,因为点很小,所以可以枚举不属于同一个连通块内的点算出距离加上两个连通块内的最大距离就是所求的答案了。注意一下最后的答案要和每个连通块内的最长路比较,如果小于就替换答案,不然会wa8,没有手写min函数会wa9。

    CODE

      1 #include <bits/stdc++.h>
      2 #define dbg(x) cout << #x << "=" << x << endl
      3 #define eps 1e-8
      4 #define pi acos(-1.0)
      5 
      6 using namespace std;
      7 typedef long long LL;
      8 
      9 template<class T>inline void read(T &res)
     10 {
     11     char c;T flag=1;
     12     while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
     13     while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
     14 }
     15 
     16 namespace _buff {
     17     const size_t BUFF = 1 << 19;
     18     char ibuf[BUFF], *ib = ibuf, *ie = ibuf;
     19     char getc() {
     20         if (ib == ie) {
     21             ib = ibuf;
     22             ie = ibuf + fread(ibuf, 1, BUFF, stdin);
     23         }
     24         return ib == ie ? -1 : *ib++;
     25     }
     26 }
     27 
     28 int qread() {
     29     using namespace _buff;
     30     int ret = 0;
     31     bool pos = true;
     32     char c = getc();
     33     for (; (c < '0' || c > '9') && c != '-'; c = getc()) {
     34         assert(~c);
     35     }
     36     if (c == '-') {
     37         pos = false;
     38         c = getc();
     39     }
     40     for (; c >= '0' && c <= '9'; c = getc()) {
     41         ret = (ret << 3) + (ret << 1) + (c ^ 48);
     42     }
     43     return pos ? ret : -ret;
     44 }
     45 
     46 const int maxn = 207;
     47 const int inf  = 0x3f3f3f3f;
     48 
     49 int n,x,y;
     50 
     51 struct node {
     52     double x, y;
     53 } a[maxn];
     54 
     55 double dis[maxn][maxn];
     56 double mixx[maxn];
     57 
     58 double cal(node a, node b) {
     59     return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
     60 }
     61 
     62 void floyd() {
     63     for ( int k = 1; k <= n; ++k ) {
     64         for ( int i = 1; i <= n; ++i ) {
     65             for ( int j = 1; j <= n; ++j ) {
     66                 if(i != j && j != k && i != k) {
     67                     if(dis[i][j] > dis[i][k] + dis[k][j] && dis[i][k] < inf && dis[k][j] < inf) {
     68                         dis[i][j] = dis[i][k] + dis[k][j];
     69                         //printf("dis[%d][%d]:%.6f
    ",i,j,dis[i][j]);
     70                     }
     71                 }
     72             }
     73         }
     74     }
     75 }
     76 
     77 int main()
     78 {
     79     read(n);
     80     for ( int i = 1; i <= n; ++i ) {
     81         read(a[i].x);
     82         read(a[i].y);
     83     }
     84     for ( int i = 1; i <= n; ++i ) {
     85         char s[maxn];
     86         scanf("%s",s+1);
     87         for ( int j = 1; j <= n; ++j ) {
     88             if(s[j] == '1') {
     89                 dis[i][j] = cal(a[i], a[j]);
     90             }
     91             else {
     92                 dis[i][j] = inf;
     93             }
     94         }
     95     }
     96     floyd();
     97     for ( int i = 1; i <= n; ++i ) {
     98         for ( int j = 1; j <= n; ++j ) {
     99             if(dis[i][j] < inf) {
    100                 if(mixx[i] < dis[i][j]) {
    101                     mixx[i] = dis[i][j];
    102                     //dbg(mixx[i]);
    103                 }
    104             }
    105         }
    106     }
    107     double ans = inf + 5;
    108     for ( int i = 1; i <= n; ++i ) {
    109         for ( int j = 1; j <= n; ++j ) {
    110             if(i != j && dis[i][j] >= inf) {
    111                 double temp = cal(a[i], a[j]);
    112                 if(ans > mixx[i] + mixx[j] + temp) {
    113                     ans = mixx[i] + mixx[j] + temp;
    114                 }
    115                 //printf("ans:%.6f mixx[%d]:%.6f mixx[%d]:%.6f temp:%.6f
    ",ans, i,mixx[i], j, mixx[j], temp);
    116             }
    117         }   
    118     }
    119     for ( int i = 1; i <= n; ++i ) {
    120         if(mixx[i] > ans)
    121             ans = mixx[i];
    122     }
    123     printf("%.6f
    ",ans);
    124     return 0;
    125 }
    View Code
  • 相关阅读:
    K短路 (A*算法) [Usaco2008 Mar]牛跑步&[Sdoi2010]魔法猪学院
    [Noi2015]软件包管理器 BZOJ4196
    [SDOI2011]染色 BZOJ2243 树链剖分+线段树
    序列操作 BZOJ2962 线段树
    斜率优化入门学习+总结 Apio2011特别行动队&Apio2014序列分割&HZOI2008玩具装箱&ZJOI2007仓库建设&小P的牧场&防御准备&Sdoi2016征途
    BZOJ1854: [Scoi2010]游戏 二分图
    BZOJ3613: [Heoi2014]南园满地堆轻絮
    BZOJ4590: [Shoi2015]自动刷题机
    [JSOI2008]星球大战starwar BZOJ1015
    Rmq Problem/mex BZOJ3339 BZOJ3585
  • 原文地址:https://www.cnblogs.com/orangeko/p/12332954.html
Copyright © 2020-2023  润新知