d数组记录每个节点的权值,最后输出时只要将当前节点所有的父亲节点的权值和加上自身节点输出,就是该节点的答案
当两个链进行合并时,其中一个链的根节点d(i)必须减去另外一个链根节点的权值d(j)这样保证i号链不会多加上j号链的权值
路径压缩时,必须更新每个子节点的权值,先将根节点暂存到p,然后用原来的父亲节点更新d,最后在将父亲节点设为p,这样从上到下,递归下来可以保证权值正确。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
typedef pair<int,int>PII;
const int N=1e4+10;
int n,m,ans;
int fa[N],d[N];
int findFa(int x) {
if(x==fa[x]||fa[fa[x]]==fa[x])return fa[x];//遇见父节点或者遇见父节点紧挨着的子节点直接返回
int p=findFa(fa[x]);
d[x]+=d[fa[x]];//更新权值
fa[x]=p;
return p;//路径压缩
}
int main(int argc, char** argv) {
cin>>n>>m;
for(int i=1; i<=n; i++)fa[i]=i;
int a,b,c;
for(int i=1; i<=m; i++) {
cin>>a>>b>>c;
if(a==1) {
int fx=findFa(b),fy=findFa(c);
if(fx!=fy) {
d[fx]-=d[fy];//权值减去以y父节点为根的权值
fa[fx]=fy; //合并
}
} else {
int fx=findFa(b);
d[fx]+=c;
}
}
for(int i=1; i<=n; i++) {
if(i==findFa(i))cout<<d[i]<<" ";//根节点直接输出
else cout<<d[i]+d[findFa(i)]<<" ";//非根节点带上根节点在输出
}
return 0;
}