1 条题解

  • 0
    @ 2023-1-17 16:02:34

    难点主要在读题上,要分清楚什么是牧区、什么是牧场、什么是大牧场。

    最短路的部分用floyd比较方便快捷。也可以用floyd的答案判断两个点是否相连。

    特别需要注意可能会出现直径不经过新加入的边的情况。

    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN = 150;
    const double INF = 200000 * 150;
    int n, m, s, t;
    int x[MAXN + 5], y[MAXN + 5];
    double dis[MAXN + 5][MAXN + 5];
    double len(int u, int v)
    {
        return sqrt((long long)(x[u] - x[v]) * (x[u] - x[v]) +
                    (long long)(y[u] - y[v]) * (y[u] - y[v]));
    }
    double maxLen[MAXN]; // maxLen[i]: 到i号点距离最远的点的距离
    signed main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        // 输入
        cin >> n;
        for (int i = 1; i <= n; i++)
            cin >> x[i] >> y[i];
        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= n; j++)
                dis[i][j] = INF;
            dis[i][i] = 0;
        }
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= n; j++)
            {
                char now;
                cin >> now; // 牧区 i 与牧区 j 的连接关系是 now
                if (now == '1')
                {
                    dis[i][j] = len(i, j);
                }
            }
        // floyd
        for (int k = 1; k <= n; k++)
            for (int i = 1; i <= n; i++)
                for (int j = 1; j <= n; j++)
                    dis[i][j] = min(dis[i][j],
                                    dis[i][k] + dis[k][j]);
        // 预处理距离每个点最远的点的距离
        for (int i = 1; i <= n; i++)
        {
            maxLen[i] = 0;
            for (int j = 1; j <= n; j++)
            {
                // double类型直接比较相等可能会有问题
                // 下面的式子逻辑上等价于 dis[i][j]!=INF
                if (abs(dis[i][j] - INF) > 1e-12)
                {
                    maxLen[i] = max(maxLen[i], dis[i][j]);
                }
            }
        }
        // 枚举可能的答案
        double ans = INF;
        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= n; j++)
            {
                // 如果 i,j 属于不同的牧场,尝试加一条边沟通两个牧场
                if (abs(dis[i][j] - INF) < 1e-12)
                {
                    if (maxLen[i] + maxLen[j] + len(i, j) < ans)
                    {
                        ans = maxLen[i] + maxLen[j] + len(i, j);
                    }
                }
            }
        }
        // 有没有可能还不如原来的直径大
        for (int i = 1; i <= n; i++)
            ans = max(ans, maxLen[i]);
        //   输出
        cout << fixed << setprecision(6) << ans << "\n";
        return 0;
    }
    
    • 1

    信息

    ID
    562
    时间
    1000ms
    内存
    128MiB
    难度
    6
    标签
    (无)
    递交数
    26
    已通过
    11
    上传者