并查集
来源:互联网 发布:华三交换机mac地址绑定 编辑:程序博客网 时间:2024/06/06 21:43
NYOJ431
样例输入
2
3 3
T 1 2
T 3 2
Q 2
3 4
T 1 2
Q 1
T 1 3
Q 1
样例输出
Case 1:
2 3 0
Case 2:
2 2 1
3 3 2
题意:起初球i是被放在i号城市的,在年代更迭,世事变迁的情况下,球被转移了,而且转移的时候,连带该城市的所有球都被移动了:T A B(A球所在的城市的所有球都被移动到了B球所在的城市),Q A(问:A球在那城市?A球所在城市有多少个球呢?A球被转移了多少次呢?)。
本题主要是用到并查集。 难点为, 怎么保存转移次数。 考虑并查集的路径压缩,就是通过路径压缩来更新转移的次数,比如每次移动时,我只需要把这个城市的根结点的转移次数+1,等到以后路径压缩时,子结点自己移动的次数加上根结点移动的次数,就是这个结点总共的移动次数。我们可以用一个tran表示此节点距离它自己现在的祖先(f数组)的转移次数,有点难理解,也就是说如图所示#include <cstdio>#include <iostream>#include <cstdlib>#include <algorithm>#include <cstring>#include <string>using namespace std;const int maxn=100100;int f[maxn],tran[maxn],sum[maxn];int af,bf,a,b,T,n,m;char s[2];void close(){ fclose(stdin); fclose(stdout); exit(0);}int getfather(int k){ if (k==f[k]) return k; return getfather(f[k]);}int find(int k){ if (f[k]==k) return k; int t=f[k]; f[k]=find(f[k]); if (t!=f[t]) tran[k]+=tran[t]; return f[k];}void work(){}void init (){freopen("dragon.in","r",stdin);freopen("dragon.out","w",stdout); scanf("%d",&T); int cnt=0; while (T--) { cnt++; printf("Case %d:\n",cnt); memset(tran,0,sizeof(tran)); memset(f,0,sizeof(f)); scanf("%d %d",&n,&m); for (int i=1;i<=n;i++) { f[i]=i; sum[i]=1; } for (int i=1;i<=m;i++) { scanf("%s",s); if (s[0]=='T') { scanf("%d %d",&a,&b); af=getfather(a); bf=getfather(b); f[af]=bf; tran[af]++; sum[bf]+=sum[af]; } else { scanf("%d",&a); af=find(a); printf("%d %d %d\n",af,sum[af],tran[a]); } } }}int main (){ init(); work(); close(); return 0;}
#include<stdio.h>int t,a,b,n,q,cnt[10005];char s[5];struct C{ int pre,num;}fa[10005];void In(){ scanf("%d %d%*c",&n,&q); for(int i=1;i<=n;i++) { fa[i].pre=i; fa[i].num=1; cnt[i]=0; //每个点移动次数一开始都是0 }}int Find(int x){ if(x!=fa[x].pre) { int tmp=fa[x].pre; fa[x].pre=Find(fa[x].pre); cnt[x]+=cnt[tmp]; // 加上它父亲的移动次数。 } return fa[x].pre;}int main(){ scanf("%d%*c",&t); for(int ca=1;ca<=t;ca++) { In(); printf("Case %d:\n",ca); for(int k=1;k<=q;k++) { scanf("%s ",s); if(s[0]=='T') { int fx,fy; scanf("%d %d%*c",&a,&b); fx=Find(a); fy=Find(b); if(fx!=fy) { fa[fy].num+=fa[fx].num; fa[fx].num=0; fa[fx].pre=fy; cnt[fx]=1; // 祖先节点只会移动一次。 } } else { scanf("%d%*c",&a); int fx=Find(a); printf("%d %d %d\n",fx,fa[fx].num,cnt[a]); } } } return 0;}
0 0
- HDU3938 并查集 并查集
- 并查集(集并查)
- HDU1232 并查集<并>
- 并查集
- 数据结构-并查集
- 并查集
- 并查集!
- 并查集
- 并查集
- 并查集
- 并查集
- 并查集总结
- 并查集学习
- 并查集
- 并查集
- 并查集
- 所谓并查集
- 并查集
- windows下jboss配置负载均衡
- 考研数据结构与算法之堆栈的建立与使用(一)
- TCP状态转换图
- LINUX设备模型BUS,DEVICE,DRIVER
- Oracle service name与instance name 不一致ORA-27101: shared memory realm does not exist
- 并查集
- BIRT修改下拉多选框
- Redis学习
- Android中的互动交流 之 Dialog
- http://blog.csdn.net/xyz_lmn/article/details/6906792#comments
- Linux Device和Driver注册过程,以及Probe的时机
- 令人作呕的OpenSSL
- linux中遇到的错误
- UVA-10755 Garbage Heap 三维子矩阵最大和