题意:有n颗龙珠分别顺序放在n个城市中,有两种操作
(1)T A B:把A所在城市的所有龙珠转运到B所在的城市。
(2)Q A :查询A所在的城市,所在城市的龙珠个数,A被转运了几次
思路:开始就是想用并查集做,但是处理细节很麻烦,每个节点记录被转运的次数,路径压缩时就可以修改节点,别的方法没想到...输入数据很多cin回超时。
#include < iostream >
#include < cstdio >
#include < algorithm >
#include < memory.h >
#include < cmath >
#include < bitset >
#include < queue >
#include < vector >
#include < map >
#include < stack >
#include < set >
#include < list >
#include < deque >
#include < cstdlib >
#include < cstring >
const int BORDER = ( 1 << 20 ) - 1 ;
const int MAXSIZE = 37 ;
const int MAXN = 20500 ;
const int INF = 0x3f3f3f3f ;
#define CLR(x,y) memset(x,y,sizeof(x))
#define MIN(m,v) (m)<(v)?(m):(v)
#define MAX(m,v) (m)>(v)?(m):(v)
#define ABS(x) ((x)>0?(x):-(x))
#define REP(i,x,y) for(i=x;i<y;++i)
#define getbit(a,i) (a&(1<<i))
#define setbit(a,i) (a|(1<<i))
using namespace std;
int pre[MAXN],ct[MAXN],num[MAXN];
int ic,n,m;
int find_set( int x)
{
int root = x;
int tmp,tmp_c,t;
t = 0 ;
while (pre[root] >= 0 )
{
root = pre[root];
t = t + ct[root];
}
ct[x] += t;
while (x != root)
{
tmp = pre[x];
tmp_c = ct[tmp];
pre[x] = root;
ct[tmp] = t;
t -= tmp_c;
x = tmp;
}
return root;
}
void union_set( const int & root1, const int & root2)
{
if (num[root1] == 0 )
return ;
num[root2] += num[root1];
num[root1] = 0 ;
++ ct[root1];
pre[root2] += pre[root1];
pre[root1] = root2;
return ;
}
int init()
{
CLR(ct, 0 );
CLR(pre, - 1 );
return 0 ;
}
int input()
{
scanf( " %d%d " , & n, & m);
int i;
REP(i, 0 ,n + 1 )
num[i] = 1 ;
return 0 ;
}
int work()
{
int i,a,b;
int pos,cnt,t;
int root1,root2;
char ch[ 3 ];
printf( " Case %d:\n " ,ic);
++ ic;
REP(i, 0 ,m)
{
scanf( " %s " ,ch);
if (ch[ 0 ] == ' T ' )
{
scanf( " %d %d " , & a, & b);
root1 = find_set(a);
root2 = find_set(b);
union_set(root1,root2);
} else
{
scanf( " %d " , & a);
pos = find_set(a);
printf( " %d %d %d\n " ,pos,num[pos],ct[a]);
}
}
return 0 ;
}
int main()
{
ic = 1 ;
int tt;
scanf( " %d " , & tt);
while (tt -- )
{
init();
input();
work();
}
return 0 ;
}