0
点赞
收藏
分享

微信扫一扫

【并查集】 hdu Dragon Balls 3635


Dragon Balls

TimeLimit: 2000/1000 MS (Java/Others)    Memory Limit:32768/32768 K (Java/Others)
Total Submission(s): 7578    Accepted Submission(s): 2806

 

ProblemDescription

Five hundred years later, the number ofdragon 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. Atfirst, 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 othercities. To save physical strength WuKong plans to take Flying Nimbus Cloud, amagical flying cloud to gather dragon balls.
Every time WuKong will collect the information of one dragon ball, he will askyou the information of that ball. You must tell him which city the ball islocated and how many dragon balls are there in that city, you also need to tellhim how many times the ball has been transported so far.

 

 

Input

The first line of the input is a singlepositive integer T(0 < T <= 100).
For each case, the first line contains two integers: N and Q (2 < N <=10000 , 2 < Q <= 10000).
Each of the following Q lines contains either a fact or a question as thefollow format:
  T A B : All the dragon balls which are in the same city with A havebeen transported to the city the Bth ball in. You can assume that the twocities are different.
  Q A : WuKong want to know X (the id of the city Ath ball is in), Y(the count of balls in Xth city) and Z (the tranporting times of the Ath ball).(1 <= A, B <= N)

 

 

Output

For each test case, output the test casenumber formated as sample output. Then for each query, output a line with threeintegers X Y Z saparated by a blank space.

 

 

SampleInput

2

3 3

T 1 2

T 3 2

Q 2

3 4

T 1 2

Q 1

T 1 3

Q 1

 

 

SampleOutput

Case 1:

2 3 0

Case 2:

2 2 1

3 3 2

 

 

Author

possessor WC

 

 

Source

​​2010ACM-ICPC Multi-University Training Contest(19)——Hostby HDU ​​

 

 

Recommend

lcy   |   Wehave carefully selected several similar problems for you:  ​​3172​​​ ​​1856​​​ ​​3234​​​ ​​3639​​​ ​​3633​​ 

 算法分析:

1.路径未压缩的并查集。

针对操作1:A所在的city中的所有龙珠转到B中,A球所在城市的龙珠数全部加到B上。

针对操作2: find(A)找到A球所在城市。转移元素个数用num数组记录,所以第二个输出直接输出num[find(A)]。

第三个是要输出A转移次数,其实就是要找带有A的连接次数,也其实就是找A一共有多少父节点,有一个父节点就说明搬运了一次。所以要用非路径压缩的并查集

2.路径压缩的并查集​​(点这里)​​(讲得好)

带权并查集统计问题

 

例题:

与普通并查集不同是新增加两个属性:

cnt[i]:该堆数量

trans[i]:该堆转移次数

操作:

在路径压缩时,trans[x] += trans[fa]

在合并时,动态更新被合并树的堆数量,并增加合并树的转移次数cnt[fy] += cnt[fx]trans[fx]++

 

 

路径压缩版代码:

 

#include<bits/stdc++.h>
using namespace std;
const int N = 10005;
int f[N], trans[N], cnt[N];
int n, m, qry, fx, fy, u, v;
char ch[5];

int find(int x){
if(x != f[x]){
int fa = f[x];
f[x] = find(f[x]);
trans[x] += trans[fa];
}
return f[x];
}

void init(int n){
for(int i = 1; i <= n; i++){
f[i] = i;
trans[i] = 0;
cnt[i] = 1;
}
}


int main()
{
int T;
scanf("%d", &T);
for(int kase = 1; kase <= T; kase++){
scanf("%d%d", &n, &qry);
init(n);
printf("Case %d:\n", kase);
for(int i = 0; i < qry; i++){
scanf("%s", ch);
if(ch[0] == 'T'){
scanf("%d%d", &u, &v);
fx = find(u), fy = find(v);
if(fx != fy){
f[fx] = fy;
cnt[fy] += cnt[fx];
trans[fx] ++;
}
}
else{
scanf("%d", &u);
v = find(u);
printf("%d %d %d\n", v, cnt[v], trans[u]);
}
}
}
return 0;
}

 

代码实现:

 

路径未压缩版代码

#include<bits/stdc++.h>
using namespace std;;
#define N 10005
int fa[N],num[N],a[N];
int cnt;
int find(int x)
{
cnt++;
return x==fa[x]?x:x=find(fa[x]);//路径未压缩
}
int main()
{

int T;
scanf("%d",&T);int k=1;
while(T--)
{
printf("Case %d:\n",k++);
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
fa[i]=i;num[i]=1;
}
char s[5];
for(int i=1;i<=m;i++)
{
scanf("%s",s);
if(s[0]=='T')
{
int x,y;
scanf("%d%d",&x,&y);
int r1=find(x),r2=find(y);
if(r1!=r2)
{
fa[r1]=r2;
num[r2]+=num[r1];
num[r1]=0;//转移后清0
}

}
else
{
int x;
scanf("%d",&x);
cnt=0;
int y=find(x);
printf("%d %d %d\n",y,num[y],cnt-1);
}

}
// for(int i=1;i<=n;i++)
// cout<<fa[i]<<" "<<find(i)<<endl;

}
return 0;

}

 

举报

相关推荐

0 条评论