(2020杭电多校第2场)A-Total Eclipse

http://acm.hdu.edu.cn/showproblem.php?pid=6763

打的时候写了个路径压缩,然后写了个用路径压缩的祖先找答案,wa成sb,纯nt做法;

画图来举例做法:

先给了你个图

先大小排序,从大往小连接

这个时候出现了个5,那么该连向哪呢

由于这个集合的根必然是最小元素,但这个元素又大于5,那么就让5成为这个集合的根

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define ll long long
using namespace std;
double pi = acos(-1);
const double eps = 1e-12;
const int maxn = 1e5 + 10;
const int inf = 1e9;

int a[maxn], p[maxn], used[maxn];

int head[maxn], cnt = 0;

struct edge {
    int to;
    int next;
}e[4 * maxn];

inline void add(int from, int to)
{
    e[++cnt] = { to,head[from] };
    head[from] = cnt;
}

int fa[maxn], f[maxn];//f链式寻祖,fa并查集路径压缩

int anc(int x)
{
    return x == fa[x] ? x : fa[x] = anc(fa[x]);
}

bool cmp(int x, int y)
{
    return a[x] > a[y];
}

int main()
{
    int t;
    scanf("%d", &t);
    while (t--)
    {
        int n, m;
        scanf("%d%d", &n, &m);
        cnt = 0;
        for (int i = 1; i <= n; i++)
        {
            scanf("%d", &a[i]);
            p[i] = i;
            fa[i] = i;
            used[i] = head[i] = f[i] = 0;
        }
        sort(p + 1, p + 1 + n, cmp);
        while(m--)
        {
            int x, y;
            scanf("%d%d", &x, &y);
            add(x, y);
            add(y, x);
        }
        for (int i = 1; i <= n; i++)
        {
            int from = p[i];
            used[from] = 1;
            for (int j = head[from]; j; j = e[j].next)
            {
                int to = e[j].to;
                if (!used[to])continue;
                to = anc(to);
                if (to == from)continue;
                fa[to] = f[to] = from;
            }
        }
        ll ans = 0;
        for (int i = 1; i <= n; i++)
            ans += a[i] - a[f[i]];
        printf("%lld
", ans);
    }
    return 0;

}
原文地址:https://www.cnblogs.com/ruanbaiQAQ/p/13372986.html