HDU3635 Dragon Balls

来源:互联网 发布:ubuntu登录密码的限制 编辑:程序博客网 时间:2024/04/29 13:51

并查集初级题目

题目链接:点击打开链接

题意:

1、每个城市初始有一个龙珠,father[i] = i初始化数组,

2、每个城市的龙珠可以移动,T A B 包含A龙珠的城市的所有龙珠都转移到包含B龙珠的城市中去

3、Q X,输出X龙珠所在城市、所在城市拥有的龙珠数量、X龙珠被移动过的次数

思路:

简单并查集,但是考虑到路径压缩会造成X龙珠移动次数计算错误(详见百度并查集路径压缩原理),所以不进行路径压缩,

直接使用一个数组c[MAXN]来记录每个地点(而不是龙珠)被移动过的次数,最后通过遍历(搜索你的根节点),每次加上经过地点的权重。

 

#include<stdio.h>#include<iostream>using namespace std;int father[10005];int c[10005];int size[10005];void init(int n)//初始化{    for(int i = 1 ; i <= n ; i ++)    {        father[i] = i;        c[i] = 0;        size[i] = 1;    }}int find(int x)//由于路径压缩有后遗症{//因此不进行路径压缩    int i = x;    while(father[i] != i)    {        i = father[i];    }    return i;}int f(int x){//使用函数求一个每个球走过的地方//对于每个球来说,遍历数组,他走过的路径为每个地点的c[i]值    int i = x;    int ans = 0;    while(father[i] != i)    {        ans += c[i];        i = father[i];    }    return ans;}void merge(int x,int y){//合并操作,同时计算每个地点有几个球    int fx = find(x);    int fy = find(y);    size[fy] += size[fx];    size[fx] = 0;    if(fx!=fy)    {        father[fx] = fy;    }}int main(){    int n,m;    int x,y;    int T;    scanf("%d",&T);    int kk = T;    while(T--)    {        scanf("%d %d",&n,&m);        printf("Case %d:\n",kk-T);        init(n);        for(int i = 1 ; i <= m; i ++)        {            char t;            int a;            getchar();            scanf("%c",&t);            if(t == 'T')            {                scanf("%d %d",&x,&y);                c[find(x)]++;//对应每一个地点使用次数加一                merge(x,y);            }            else if(t == 'Q')            {                scanf("%d",&a);                printf("%d %d %d\n",find(a),size[find(a)],f(a));            }        }    }    return 0;}


 

0 0