hdu 3635 Disjoint并查集+路径压缩

来源:互联网 发布:nginx默认安装路径 编辑:程序博客网 时间:2024/05/21 19:32

原题链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=3635
题意:
起初球i是被放在i号城市的,在年代更迭,世事变迁的情况下,球被转移了,而且转移的时候,连带该城市的所有球都被移动了:T A B(A球所在的城市的所有球都被移动到了B球所在的城市),Q A(问:A球在那城市?A球所在城市有多少个球呢?A球被转移了多少次呢?)

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=10000+5;int fa[maxn];   //父节点int num[maxn];  //节点数int dist[maxn]; //dist[i]表第i个节点到其父节点的距离(即第i个节点一共被转移了几次才连接上它当前的父节点的)//为了解决引入路径压缩带来的转移次数信息被破坏的问题,需要引入第三个数组来保存每个球的转移次数//龙珠被转移的次数就是该龙珠距离根节点的距离int findset(int x){    if(fa[x]==-1) return x;    int root=findset(fa[x]);    dist[x] += dist[fa[x]];    return fa[x]=root;}int bind(int u,int v)//将u分量加入v分量下面{    int fu=findset(u);    int fv=findset(v);    if(fu != fv)    {        num[fv] += num[fu]; //每个龙珠对应一个并查集的初始节点,然后用每个连通分量的根节点来维护num[i](即当前分量中的节点总数)        dist[fu]++;        fa[fu]=fv;        return 1;    }    return 0;}int main(){    int T;    scanf("%d",&T);    for(int kase=1; kase<=T; ++kase)    {        printf("Case %d:\n",kase);        int n,q;        scanf("%d%d",&n,&q);        for(int i=1;i<=n;i++)        {            fa[i]=-1;            num[i]=1;            dist[i]=0;        }        char str[10];        while(q--)        {            scanf("%s",str);            if(str[0]=='T')            {                int u,v;                scanf("%d%d",&u,&v);                bind(u,v);            }            else if(str[0]=='Q')            {                int u;                scanf("%d",&u);                int root=findset(u);                printf("%d %d %d\n",root,num[root],dist[u]);            }        }    }    return 0;}
0 0