今天打比赛前写的一道带权并查集
题意 搬砖头 把包含有 a的砖头堆里的 所有砖头 转移到 包含b的砖头堆上 问 K砖头下有几块砖头
思路 :并查集 额外开两个数组 一个记录这堆砖头堆的砖头高度 另一个记录k砖头下有几块砖头 每次合并的时候更新砖头高度 和被合并的砖头堆 最底下砖头 下面有几块砖头 用户find 时更新
ac code
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <queue> #include <algorithm> #include <cstdlib> using namespace std; const int maxn=30005; int root[maxn],under[maxn],height[maxn]; void init(int n) { for(int i=0;i<=n;i++) root[i]=i,under[i]=0,height[i]=1; } int fin(int x) { if(root[x]==x) return x; int rot=root[x]; root[x]=fin(root[x]); under[x]+=under[rot];//递归更新要查找的点 return root[x]; } void Union(int u,int v) { int ru=fin(u); int rv=fin(v); if(ru==rv) return; root[ru]=rv;//ru堆的最底下变成了rv under[ru]=height[rv];//ru砖头下有rv块砖头 height[rv]+=height[ru];//更新rv堆砖头高度 } int main() { char ch[5]; int u,v,n; while(scanf("%d",&n)!=EOF) { init(n<30000?n:30000); for(int i=0;i<n;i++) { scanf("%s",ch); if(ch[0]=='M') { scanf("%d%d",&u,&v); Union(u,v); } else { scanf("%d",&u); fin(u);//这里必须有 因为算法是延迟更新的 这里如果不查找 就不会更新 printf("%d\n",under[u]); } } } return 0; } 现在也找不到什么带权并查集的题了 也就发了两篇博客 总的来说 带权并查集的核心在于 延迟更新
建图的时候理清楚合并的集合的关系就好办了
