HDU 2818 Building Block(带权并查集)

【题目链接】:Click here~~

【题意】:

给 n 块砖头,开始各为一堆,两种操作:

1、把 X 所在的那一堆箱子里的砖头放到 Y 所在的那一堆上面。

2、询问 X 下面有多少块砖。

【解题思路】:好像大家都叫它带权并查集,那为了方便,这里也这样叫吧,因为涉及前面的和后面的箱子个数,对应的查找操作,一开始想用结构体来写,在结构体里定义每个箱子的前驱和后继,每次输入的时候统计一下相应的前驱和后继的个数,后来发现不行,因为涉及到合并操作,比如说M 2 4 M 2 6连续出现两个2,用结构体是不容易实现的,这时候发挥并查集的效果了,在合并的时候分别更新 (1)Sum[i]=1;//i所在的箱子总数,(2)upsum[i]=0;//i下面箱子数,最后C
a时直接输出upsum[a]

代码:

/*
Author:HRW
带权并查集
*/
#include <bits/stdc++.h>
using namespace std;
const int N=30005;
int father[N],Sum[N],upsum[N],n,m,a,b,T;
char ch[4];
int find(int x){
    if(x!=father[x]){
        int temp=find(father[x]);
        upsum[x]+=upsum[father[x]];
        father[x]=temp;
    }
    return father[x];
}
void Union(int a,int b)
{
    int pa=find(a);
    int pb=find(b);
    if(pa!=pb){
        upsum[pa]=Sum[pb];//合并pa下面pb的所有箱子
        Sum[pb]+=Sum[pa];//pb所在的堆的箱子总数
        father[pa]=pb;//合并根节点
    }
}
void init(){
    for(int i=0; i<N; i++)
    {
        father[i]=i;
        Sum[i]=1;//i所在的箱子总数
        upsum[i]=0;//i下面箱子数
    }
}
int main()
{
    while(scanf("%d",&T)!=EOF){
        init();
        for(int i=0; i<T; i++){
            scanf("%s",ch);
            if(ch[0]=='M'){
                scanf("%d%d",&a,&b);
                Union(a,b);
            }
            else{
                scanf("%d",&a);
                find(a);
                printf("%d\n",upsum[a]);
            }
        }
    }
    return 0;
}
时间: 2024-11-12 08:44:10

HDU 2818 Building Block(带权并查集)的相关文章

hdu 2818 Building Block(带权并查集)

题目: 链接:点击打开链接 题意: 有N个积木,1到N编号.进行一些操作P次,M:X Y把X积木放到Y的上面,如果X和Y相等请忽略.C:X 计算X积木下的积木数目. 思路: 带权并查集的题目,定义数组sum[i]表示i积木下面积木的数目.遇到操作M,就把X和Y合并到同一个集合中.我们视每个结点为1个 Pile,其中rank[i]就表示每个Pile处的积木的个数,Initially, there are N piles, and each pile contains one block.所以,ra

hdu 2818 Building Block (带权并查集,很优美的题目)

Problem Description John are playing with blocks. There are N blocks (1 <= N <= 30000) numbered 1...N.Initially, there are N piles, and each pile contains one block. Then John do some operations P times (1 <= P <= 1000000). There are two kinds

HDU 3047 Zjnu Stadium 带权并查集

题目来源:HDU 3047 Zjnu Stadium 题意:给你一些人 然后每次输入a b c 表示b在距离a的右边c处 求有多少个矛盾的情况 思路:用sum[a] 代表a点距离根的距离 每次合并时如果根一样 判断sum数组是否符合情况 根不一样 合并两棵树 这里就是带权并查集的精髓 sum[y] = sum[a]-sum[b]+x 这里y的没有合并前b的根 #include <cstdio> #include <cstring> using namespace std; cons

HDU 3172 Virtual Friends 带权并查集 -秩

ll T; while(~scanf("%d",&T)){ while(T--) { = = ... 思路: 用秩合并,看了题解才发现 if(fx == fy)要输出当前集合的秩而不是0... #include <cstdio> #include <iostream> #include <algorithm> #include <string.h> #include <vector> #include <map&

HDU 3172 Virtual Friends(带权并查集)

题目地址:HDU 3172 带权并查集水题.每次合并的时候维护一下权值.注意坑爹的输入.. 代码如下: #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdlib.h> #include <math.h> #include <ctype.h> #include <queue> #inclu

hdu 5441 Travel 离线带权并查集

Travel Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5441 Description Jack likes to travel around the world, but he doesn’t like to wait. Now, he is traveling in the Undirected Kingdom. There are n cities and m

HDU 3635 Dragon Balls(带权并查集)

题目地址:HDU 3635 加权并查集水题. 用num数组维护该城市有多少龙珠,用times数组维护每个龙珠运输了多少次.num数组在合并的时候维护.times数组由于每个都不一样,所以要在找根的时候递归来全部维护. 最终,x龙珠所在的城市就是x节点所在的根,x结点所在的跟的num数组值是该城市的龙珠数.times[x]为该龙珠运输了多少次. 代码如下: #include <iostream> #include <cstdio> #include <string> #i

hdu 5441 travel 离线+带权并查集

Time Limit: 1500/1000 MS (Java/Others)  Memory Limit: 131072/131072 K (Java/Others) Problem Description Jack likes to travel around the world, but he doesn’t like to wait. Now, he is traveling in the Undirected Kingdom. There are n cities and m bidir

How Many Answers Are Wrong HDU - 3038 (经典带权并查集)

题目大意:有一个区间,长度为n,然后跟着m个子区间,每个字区间的格式为x,y,z表示[x,y]的和为z.如果当前区间和与前面的区间和发生冲突,当前区间和会被判错,问:有多少个区间和会被判错. 题解:x,y,z表示从x开始到y的所有数字的和,那么x-1就表示从(x-1,y]的区间和.我们可以对区间的左边x-1寻找他的左端点,同时对区间右边y也寻找他的左端点,如果这两个左端点相等(设为l)那么他就是将区间了[l,y]拆分成了[l,x-1]和[x,y],我们判断一下区间和是不是相等的就可以了也就是w[

HDU - 3038 / 3048 (带权并查集) (待补)

题目链接:点我点我 题意: 题解: 两题代码差不多,放个3047的. 1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 using namespace std; 5 6 const int N=200010; 7 int Father[N],value[N]; 8 9 int find(int x){ 10 if(x==Father[x]) return x; 11 int tmp=Fa