1. 程式人生 > 實用技巧 >(2020杭電多校第2場)A-Total Eclipse

(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\n", ans);
    }
    return 0;

}