HDU 3635 Dragon Balls [并查集]

题意:有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 ;
}

 

你可能感兴趣的:(drag)