Luogu P2847 [USACO20DEC]Moocast(gold)奶牛广播-金

解题思路

要保证图是强连通的,用因为给出的边全部都是双向边。考虑树形的结构,在一棵树上的$N$个节点一定是强连通的。他们都能够互相到达。又要保证树上的$n-1$条边中的最长的一条边最小。那就用Kruskal求一个最小生成树,找出其中的最长边,平方就是答案

附上代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>

using namespace std;

const int maxn = 1e3+3;
int n, x[maxn], y[maxn], cnt, tot, f[maxn];
double Ans, d[maxn][maxn];
struct Edge {
    int u, v;
    double w;
}ed[maxn * maxn];
inline bool cmp(Edge a, Edge b) {
    return a.w < b.w;
}
inline int find(int x) {
    if(x == f[x]) return x;
    else return f[x] = find(f[x]);
}
inline void Kruskal() {
    for(int i=1; i<=n; i++) f[i] = i;
    for(int i=1; i<=n; i++) {
        for(int j=1; j<=n; j++) {
            if(i != j) {
                ++cnt;
                ed[cnt].u = i, ed[cnt].v = j, ed[cnt].w = d[i][j];
                //printf("%d %d %.2lf\n", ed[cnt].u, ed[cnt].v, ed[cnt].w);
            }
        }
    }
    sort(ed+1, ed+1+cnt, cmp);
    for(int i=1; i<=cnt; i++) {
        int xx = find(ed[i].u), yy = find(ed[i].v);
        if(xx != yy) {
            f[xx] = find(yy);
            tot ++;
            Ans = ed[i].w;
        }
        if(tot == n-1) {
            break;
        }
    }
}

int main() {
    scanf("%d", &n);
    for(int i=1; i<=n; i++) {
        scanf("%d%d", &x[i], &y[i]);
    }
    for(int i=1; i<=n; i++) {
        for(int j=1; j<=n; j++) {
            d[i][j] = sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
            //printf("%.2lf ", d[i][j]);
        }
        //printf("\n");
    }
    Kruskal();
    printf("%.0lf", Ans * Ans);
}

猜你喜欢

转载自www.cnblogs.com/bljfy/p/9463802.html
今日推荐