标签:
6 M 1 6 C 1 M 2 4 M 2 6 C 3 C 4
1 0 2
并查集:ran[x] 表示 在x下面的立方体数,sum[x]表示x所在堆的总立方体数,随着立方体的叠放,sum值只记载在根节点处,在unite()中,ran值也只是记载在fx上,容易理解ran[fx] += sum[fy];在之后find()中再将一个个节点经行更新ran[x] += ran[fx];
#include<cstdio> #include<algorithm> #include<cstring> const int maxn = 3e4+5; using namespace std; int pre[maxn]; int ran[maxn]; int sum[maxn]; void init(){ for(int i = 1; i <= maxn; i++){ pre[i] = i; ran[i] = 0; sum[i] = 1; } } int find(int x){ if(pre[x] == x) return pre[x]; int fx = pre[x]; pre[x] = find(pre[x]); ran[x] += ran[fx]; return pre[x]; } void unite(int x,int y){ int fx = find(x); int fy = find(y); pre[fx] = fy; ran[fx] += sum[fy]; sum[fy] += sum[fx]; } int main(){ int p,x,y; char ch[2]; init(); scanf("%d",&p); while(p--){ scanf("%s",ch); if(ch[0] == ‘M‘){ scanf("%d%d",&x,&y); unite(x,y); } else { scanf("%d",&x); int tep = find(x); printf("%d\n",ran[x]); } } return 0; }
另外,通过这道题终于懂了并查集的find()函数,原来我之前都是一知半解= =!
举个例子说明一下:
int find(int x){ if(pre[x] == x) return pre[x]; int fx = pre[x]; pre[x] = find(pre[x]); ran[x] += ran[fx]; return pre[x]; }
1 -> 2 -> 3 -> 4 -> 5;
x = 1, fx = 2; -> x = 2, fx = 3; -> x = 3, fx = 4; -> x = 4, fx = 5; -> x = 5, fx = 5;
pre[4] = pre[5](5); -> pre[3] = pre[4](5); -> pre[2] = pre[3](5); -> pre[1] = pre[2](5);
ran[4] += ran[5]; -> ran[3] += ran[4]; -> ran[2] += ran[3]; -> ran[1] += ran[2];
这样就形成了一颗高度为2的树,除根节点外全部节点指向根节点,搜索起来减少了不少的复杂度,膜拜!
而ran值也在其中是从根节点经行更新;
并查集真是so cool!
标签:
原文地址:http://www.cnblogs.com/ACMessi/p/4837265.html