【最小生成树】畅通工程再续 HDU

畅通工程再续 HDU - 1875

思路:

1.将一条边加入最小生成树时有额外条件,注意一下即可。

2.如果所有点均可连通,那么应该在同一个集合里,也就是有同一个根节点;如果出现了不同的根节点说明没有全部连通。

然后就是套模板。

const int maxn = 100 + 10;
const int maxm = maxn * maxn ;

int fa[maxn], tmp[maxm];
int u[maxm], v[maxm];
double w[maxm];
int n, m;
double ans = 0;

struct node {
    double x, y;
}N[maxn];

int find(int x) { 
    return fa[x] == x ? x : fa[x] = find(fa[x]); 
}
bool cmp(int i, int j) {
    return w[i] < w[j];
}

double count(node t1,node t2) {
    double dx = t1.x - t2.x;
    double dy = t1.y - t2.y;
    return sqrt(dx * dx + dy * dy);
}

void solve() {
    for (int i = 0; i < maxn; i++) fa[i] = i;
    for (int i = 0; i < m; i++) tmp[i] = i;
    sort(tmp, tmp + m, cmp);
    for (int i = 0; i < m; i++) {
        int e = tmp[i];
        int from = find(u[e]);
        int to = find(v[e]);
        if (from != to && w[e]>=10 && w[e]<=1000) {
            ans += w[e];
            fa[from] = to;
        }
    }
}

int main()
{
    //ios::sync_with_stdio(false);
    int t; cin >> t; while (t--) {
        m = 0;
        ans = 0;
        cin >> n;
        for (int i = 1; i <= n; i++) {
            cin >> N[i].x >> N[i].y;
            for (int j = i - 1; j >= 1; j--) {
                u[m] = i; v[m] = j; 
                w[m] = count(N[i], N[j]);
                m++;
            }
        }
        solve();
        int ok = 1;
        int root = find(1);
        for (int i = 2; i <= n; i++) {
            if (root != find(i)) {
                ok = 0;
                break;
            }
        }
        if (ok) printf("%.1f
", ans * 100);
        else printf("oh!
");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/streamazure/p/13504380.html