寒假做题记录

1.20 Tue

LG P1522

牧场:联通的牧区;牧场的直径:任意两个牧区的距离(最短路)的最大值;目的是连接两个牧场,使得新的大牧场的直径最小,输出的新的直径

1.肯定先求连通块
2.\(N\leq 150\) 且要求任意两个点之间的最短路,所以用 floyd
3.考虑一个新连通块(原来有 \(A,B\) 两个牧场,连了一条 \(i\rightarrow j,\ i\in A, j\in B\) 的边)直径的情况:
①.原来 \(A\) 牧场的直径
②.原来 \(B\) 牧场的直径
③. \(i\rightarrow j\) 的边权 + \(i\)\(A\) 连通块里能达到最远的距离 + \(j\)\(B\) 连通块里能达到的最远距离
4.需要处理的东西:每个连通块内的直径,对于一个连通块内的一个点能达到的最远距离

namespace Solution{
    int n;
    PII a[maxn];
    int p[maxn];
    double dis[maxn][maxn], maxdis[maxn], maxblock[maxn];
    void init(){
        For (i, 1, n) p[i] = i;
    }
    int find(int x){
        if (x == p[x]) return x;
        return p[x] = find(p[x]);
    }
    void combine(int x, int y){
        int r1 = find(x), r2 = find(y);
        if (r1 == r2) return;
        p[r1] = r2;
    }
    double getdis(double xx1, double yy1, double xx2, double yy2){
        return sqrt((xx1 - xx2) * (xx1 - xx2) + (yy1 - yy2) * (yy1 - yy2));
    }
    void Main(){
        cin >> n;
        init();
        For (i, 1, n) cin >> a[i].fi >> a[i].se;
        For (i, 1, n){
            string s; cin >> s;
            For (j, 0, sz(s) - 1){
                int jj = j + 1;
                if (s[j] == '1'){
                    combine(i, jj);
                    dis[i][jj] = getdis(a[i].fi, a[i].se, a[jj].fi, a[jj].se);
                } else if (s[j] == '0' && i == jj){
                    dis[i][jj] = 0;
                } else{
                    dis[i][jj] = inf;
                }
            }
        }
        For (k, 1, n){
            For (i, 1, n){
                For (j, 1, n){
                    upmin(dis[i][j], dis[i][k] + dis[k][j]);
                }
            }
        }
        For (i, 1, n){
            For (j, 1, n){
                if (find(i) == find(j)){
                    upmax(maxdis[i], dis[i][j]);
                }
                upmax(maxblock[find(i)], maxdis[i]);
            }
        }
        double ans = (double)inf;
        For (i, 1, n){
            For (j, 1, n){
                int r1 = find(i), r2 = find(j);
                if (r1 == r2) continue;
                double k1 = maxblock[r1];
                double k2 = maxblock[r2];
                double k3 = maxdis[i] + maxdis[j] + getdis(a[i].fi, a[i].se, a[j].fi, a[j].se);
                ans = min(ans, max(k1, max(k2, k3)));
            }
        }
        cout << fixed << setprecision(6) << ans << endl;
    }
};
posted @ 2026-01-20 15:04  xyzEcho  阅读(3)  评论(0)    收藏  举报