题目大意:输入一个整数t,表示测试用例数.输入两个整数n,m,分别表示节点数和对接点的操作次数。在接下来的m行中,有两种命令
T a b 。表示将a节点所在的城市中的所有节点都移到b节点所在的城市中
Q a 。表示输出 a节点所在的城市 a节点所在城市的节点数 a节点的移动次数
解题思路:并查集
1)将a节点所在城市中的所有节点都移动到b节点所在城市体现在:
if(cmd[0] == 'T'){
int a,b;
scanf("%d%d",&a,&b);
int fa = find(a);
int fb = find(b);
join(fa,fb);
}
这是要注意的。而不是直接join(a,b);因为这一句的意思是将a节点y与b节点合并
代码如下:
/*
* 3635_3.cpp
*
* Created on: 2013年8月23日
* Author: Administrator
*/
#include <iostream>
using namespace std;
/**
* father[i] : 用来保存当前节点的父亲节点
* rank[i] :之前是用来保存当前节点的秩,在这里用来保存当前节点移动次数
* ad[i] :用来当前节点所在城市所拥有的节点的数量
*
*/
int father[10000];
int rank [10000];
int ad[10000];
int find(int x){
if( x == father[x]){
return x;
}
int t = find(father[x]);
rank[x] += rank[father[x]];
father[x] = t;
return father[x];
}
void join(int x , int y){
if( x == y){
return ;
}
father[x] = y;//将x的父亲设置为 y
rank[x] = 1;//这是x就移动了一次
ad[y] += ad[x];//y节点所在城市的节点数 +=x节点所在城市的节点数
}
void make_set(int n){
int i;
for( i = 1 ; i <= n ; ++i){
father[i] = i;
ad[i] = 1;//一开始假设每个城市只有一个节点
}
}
int main(){
int t;
scanf("%d",&t);
int count = 1;
while(t--){
memset(rank,0,sizeof(rank));
printf("Case %d:\n",count++);
int n,m;
scanf("%d%d",&n,&m);
make_set(n);
int i;
for( i = 1; i <= m ; ++i){
char c[5];
scanf("%s",c);
if(c[0] == 'T'){
int a,b;
scanf("%d%d",&a,&b);
int fa = find(a);//注意: T a b 是将节点a所在的城市的所有节点移动到b节点所在城市,而不是将a节点移动到b节点
int fb = find(b);
join(fa,fb);
}else if(c[0] == 'Q'){
int a;
scanf("%d",&a);
int fa = find(a);
//输出格式是:当前节点所在城市 当前节点所在城市的节点数 当前节点被移动的次数
printf("%d %d %d\n",fa,ad[fa],rank[a]);
}
}
}
}