HDU 3635:Dragon Balls

题目地址:

http://acm.hdu.edu.cn/showproblem.php?pid=3635

题目类型: 并查集

题目:

Five hundred years later, the number of dragon balls will increase unexpectedly, so it's too difficult for Monkey King(WuKong) to gather all of the dragon balls together.

His country has N cities and there are exactly N dragon balls in the world. At first, for the ith dragon ball, the sacred dragon will puts it in the ith city. Through long years, some cities' dragon ball(s) would be transported to other cities. To save physical strength WuKong plans to take Flying Nimbus Cloud, a magical flying cloud to gather dragon balls.
Every time WuKong will collect the information of one dragon ball, he will ask you the information of that ball. You must tell him which city the ball is located and how many dragon balls are there in that city, you also need to tell him how many times the ball has been transported so far.

样例输入:

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

题目大意:

有N的龙珠,编号为1~N,开始时分别分布在编号为1~N的城市。

然后如果是输入T a b,那么进行移动, 把编号a的龙珠所在的城市的所有龙珠移动到编号b龙珠所在的城市。

输入Q a, 那么输出a龙珠所在的城市, a龙珠所在城市有的龙珠的个数, 以及a龙珠移动的次数。

思路与总结:

首先,感觉这题确实是一道很好的并查集题目,可以加深对并查集和压缩路径的理解。

做这题有点略纠结,WA了很多次,说明我对并查集的理解还是不够。

求一个龙珠在那个城市很好办, 只需要find(x),找到x的根结点,即是x所在的城市

求一个城市有多少个龙珠也很好办, 只需要加上一个rank数组,用来表示并查集的秩,及树的高度,就是那个城市的龙珠的数量。

而求一个龙珠移动的次数,比较难搞,也正式我纠结之处。

首先,当一座城市的龙珠全部移动到另一个城市之后,那么这个城市的龙珠数量变为0, 也就是说没有龙珠是在这个城市了,那么之后都不会再有龙珠移动到这个空城市。因为T a x,必须是移动到龙珠x所在的城市,而现在已经没有龙珠落在空城市了,对于任意龙珠x,都不会是落在空城市。最后可以得出结论,一个城市只能移动一次。

开一个数组num表示各个求的移动次数。

每次移动时, 设是T a b, 那么b所在城市(即b的根结点)的最初始的球, 是这个球的第一次移动, 这时给初始球的移动次数置为1。

光光是这样做的话,还不够。因为这样只增加了根结点的初始那个球的次数,还有其他球在这个跟结点的次数还没有加。

别急, 这个这个步骤可以留给路径压缩的时候做。

还没进行路径压缩时,它的父亲是以前的那个跟结点,而这时候,之前欠下来的债也还了,让它的移动次数加上它所有祖宗的移动次数(这个是关键,也比较难理解)。

最后,它只想了新结点。 次数也跟新了。

进行路径压缩之后,每个球的父亲结点就是它所在的城市。

#include<iostream>
#include<cstdio>
#include<cstring>
#define MAXN 10002
using namespace std;
int N, Q, father[MAXN], rank[MAXN], num[MAXN];  

void init(){
    for(int i=1; i<=N; ++i){
        father[i] = i, rank[i] = 1, num[i]=0;
    }
}  

int find(int x){
    if(x==father[x]) return x;
    int t=father[x];
    father[x] = find(father[x]);
    num[x] += num[t];
    return father[x];
}  

void Union(int x,int y){
    int a=find(x);
    int b=find(y);
    if(a!=b){
        father[a] = b;
        rank[b] += rank[a];
        num[a] = 1; // 这是球a第一次移动
    }
}  

int main(){
#ifdef LOCAL
    freopen("input.txt","r",stdin);
#endif
    int T,a,b,k,cas=1;  char cmd[2];
    scanf("%d", &T);
    while(T--){
        printf("Case %d:\n",cas++);
        scanf("%d %d", &N,&Q);
        init();
        for(int i=0; i<Q; ++i){
            scanf("%s", cmd);
            if(cmd[0]=='T'){
                scanf("%d %d", &a, &b);
                Union(a, b);
            }
            else{
                scanf("%d", &k);
                int x = find(k);
                int cnt=0;
                printf("%d %d %d\n", x, rank[x],num[k]);
            }
        }
    }
    return 0;
}

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索移动
, 结点
, 一个
, (Dragon
, The
, 次数
, 城市
java选择所在城市
balls、great balls of fire、balls是什么意思、buckyballs、blue balls,以便于您获取更多的相关知识。

时间: 2024-08-16 05:53:55

HDU 3635:Dragon Balls的相关文章

hdu 3635 Dragon Balls

点击打开hdu 3635 思路: 并查集 分析: 1 题目说有n个城市每一个城市有一个龙珠编号为i,现在有m行的输入包括两种的情况 T x y 把x所在的集合的所以龙珠转移到y集合上 Q x 询问x所在集合的龙珠的个数 2 我们利用rank[x]表示的是根节点为x的集合的元素的个数,但是现在我们发现求转移的次数不好求,刚开始我用的是一个vector数组来保存,比如v[x]表示以x为根节点的集合的元素,那么如果是把fx这个集合并到fy上的话,那么我们枚举v[fx].但是这个方法TLE了 3 后来看

HDU 3461:Code Lock(并查集+二分求幂)

链接: http://acm.hdu.edu.cn/showproblem.php?pid=3461 原题: Problem Description A lock you use has a code system to be opened instead of a key. The lock contains a sequence of wheels. Each wheel has the 26 letters of the English alphabet 'a' through 'z',

HDU 3926:Hand in Hand(同构图)

链接: http://acm.hdu.edu.cn/showproblem.php?pid=3926 原题: Hand in Hand Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 122768/62768 K (Java/Others) Total Submission(s): 731    Accepted Submission(s): 294 Problem Description In order to get rid o

HDU 1558:Segment set, 计算几何+并查集

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1558 题目类型: 计算集合 , 并查集 题目: A segment and all segments which are connected with it compose a segment set. The size of a segment set is the number of segments in it. The problem is to find the size of some

HDU 2048:递推&amp;amp;错排概率

神.上帝以及老天爷 http://acm.hdu.edu.cn/showproblem.php?pid=2048 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Problem Description HDU 2006'10 ACM contest的颁奖晚会隆重开始了! 为了活跃气氛,组织者举行了一个别开生面.奖品丰厚的抽奖活动,这个活动的具体要求是这样的: 首先,所有参加晚会的人员

hdu3635 Dragon Balls(带权并查集)

/* 题意:有N个城市, 每一个城市都有一个龙珠(编号与城市的编号相同),有两个操作 T A ,B 将标号为A龙珠所在城市的所有的龙珠移动到B龙珠所在城市中! 思路:并查集 (压缩路径的时候将龙珠移动的次数进行更新) */ #include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #define M 10005 using namespace std; int f[M]

HDU 1140 War on Weather:三维点之间距离

HDU 1140:http://acm.hdu.edu.cn/showproblem.php?pid=1140 大意:地球球心是(0,0,0),给你k个卫星以及k个卫星的三维坐标(以球心为基准),m个地球上的点以及m个点的三维坐标(以球心为基准),问有多少个点是能被卫星覆盖到的,输出数量. 思路: 求出卫星与地球切线的长度,在地球上,与卫星连线的长度小于切线长度的肯定都能看到. 更多精彩内容:http://www.bianceng.cnhttp://www.bianceng.cn/Program

HDU 1115 Lifting the Stone:求多边形重心

HDU 1115:http://acm.hdu.edu.cn/showproblem.php?pid=1115 大意:给你个n,有n个点,然后给你n个点的坐标,求这n个点形成的多边形的重心的坐标. 更多精彩内容:http://www.bianceng.cnhttp://www.bianceng.cn/Programming/sjjg/ struct point { double x, y; } P[1000010]; struct line { point a, b; } ; double xm

HDU 2985 Another lottery(水题)

HDU 2985:http://acm.hdu.edu.cn/showproblem.php?pid=2985 大意: 给你n个人,每个人买m次彩票,第i次的奖金是2的i次方,求每个人赢的比其他人都多的可能性是多少. 思路: 就是只看最后一次就行,2的i次方,对于每个人来说,最后一次的奖要比前面的大很多,所以直接只看最后一次,算出概率gcd一下就行了. 更多精彩内容:http://www.bianceng.cnhttp://www.bianceng.cn/Programming/sjjg/ #i