【样例输入】
4 8
1 1 2
2 1 10
2 3 5
1 4 1
2 2 2
1 1 2
1 2 4
2 2 1
【样例输出】
13 13 5 3
看到这种合并题,第一反应应该就是dsu啊?那我们考虑怎么搞并查集,普通并查集显然8太行(或者维护起来很麻烦),观察性质可以知道,我们只需要维护当前点p及其当前点p的root的差值就可以了。那就好办了啊,带权并查集直接上啊,所以每个点最后的结果就是它与它祖先root的差值+root自身的值就可以了。
我们对于操作1,那就是非连通块的话合并并且更新其d值,已经是连通块就continue掉。
我们对于操作2,其实意思就是在他祖先点进行修改就可以了,因为我们要求的最终结果是祖先自己的值+该点与祖先的差值。
#include<bits/stdc++.h>
#define ll long long
const int maxn = 1e4 + 5;
int fa[maxn], d[maxn], now[maxn], n, m;
int find(int x) {
if (x != fa[x]) {
int temp = fa[x];
fa[x] = find(fa[x]);
d[x] += d[temp];
}
return fa[x];
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) fa[i] = i;
while (m--) {
int op; scanf("%d", &op);
if (op == 1) {
int a, b; scanf("%d%d", &a, &b);
int eu = find(a), ev = find(b);
if (eu != ev) {
fa[ev] = eu;
d[ev] = now[ev] - now[eu];
}
}
else {
int p, t; scanf("%d%d", &p, &t);
int rt = find(p);
now[rt] += t;
}
}
for(int i= 1;i <= n;++i) {
printf("%d ", now[find(i)] + d[i]);
}
puts("");
}