带权并查集(核心): 1、路压要维护权值(考虑怎么维护) 2、合并时也要维护权值(考虑怎么维护) 3、并查集一般对根节点进行操作
dis与差分: 1、差分是当前元素与前一个元素的差值 ,dis是当前节点与父节点的差值 2、差分做前缀和为原数组 ,dis对祖先做前缀和为原权值
f[x]表示当前x的父亲(未更新)
#include<bits/stdc++.h>
using namespace std;
int const N=1e4+7;
int n,m;
int f[N],w[N],dis[N]; //w表示集合根节点的权值 //dis[i]表示i与父节点(权值)的差值,有点类似差分
int find(int x){
if(f[x]!=x){
int fx=f[x];
f[x]=find(f[x]);
dis[x]+=dis[fx]; //路压维护权值 //以后难一点的题目,这一步可以画图,举例子,来推出如何维护
}
return f[x];
}
void merge(int a,int b){
int fx=find(a),fy=find(b);
f[fx]=fy;
dis[fx]=w[fx]-w[fy]; //合并维护权值 //以后难一点的题目,这一步可以画图,举例子,来推出如何维护
}
int main(){
cin >> n >> m;
for(int i=1;i<=n;++i) f[i]=i;
int op,a,b;
while(m--){
cin >> op >> a >> b;
if(op==1){
if( find(a)!=find(b) ) merge(a,b);
}
else w[find(a)]+=b;
}
for(int i=1;i<=n;++i){
cout << w[find(i)]+dis[i] << " ";
}
return 0;
}