(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
#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;
}