OJ题目:click here~~
题目分析:
L a b时,将a和b加入一个集合,且 a , b 不同 (a ,b 不同,a , c 不同 那么b c 相同)。
Q a b时,若a和b的权值差为奇数,则方向相反,否则方向相同。 不在一个几个就无法查询。
D a时, 由于被删除的节点的信息以后还会用到,所以就新建一个点作为该点拿出去。
S a时, 直接查询a的祖先节点上储存的集合元素个数。
AC_CODE
const int maxn = 600008 ;
int n , m ;
int rep[maxn] ;
int fa[maxn] ;
int dis[maxn] ;
int sum[maxn] ;
void init(){
for(int i = 0 ;i <= n + m;i++){
fa[i] = i ;
rep[i] = i ;
sum[i] = 1 ;
dis[i] = 0 ;//一定要是0.。。为什么呢?
}
}
int father(int u){
if(u == fa[u]) return u ;
int t = father(fa[u]) ;
dis[u] += dis[fa[u]] ;
return fa[u] = t ;
}
void Merg(int u , int v){
int fu = father(u) ;
int fv = father(v) ;
if(fu != fv){
fa[fu] = fv ;//不能fa[fv] = fu 为什么呢??
sum[fv] += sum[fu] ;
dis[u] = dis[v] + 1;
}
}
void Dele(int u){
int fu = father(rep[u]) ;
sum[fu]-- ;
n++ ;
rep[u] = n ;
//fa[n] = n ;
}
void Query(int u , int v){
if(father(u) != father(v)) puts("Unknown") ;
else if(abs(dis[u] - dis[v])&1) puts("Different") ;
else puts("Same") ;
}
int main(){
//freopen("in.txt" , "r" , stdin) ;
while(scanf("%d%d",&n,&m) != EOF){
init() ;
int u , v ;
char s[10] ;
while(m--){
scanf("%s",s) ;
if(s[0] == 'L'){
scanf("%d%d",&u , &v) ;
Merg(rep[u] , rep[v]) ;
}
else if(s[0] == 'D'){
scanf("%d" , &u) ;
Dele(u) ;
}
else if(s[0] == 'Q'){
scanf("%d%d",&u , &v) ;
Query(rep[u] , rep[v]) ;
}
else if(s[0] == 'S'){
scanf("%d",&u) ;
printf("%d\n" , sum[father(rep[u])]) ;
}
}
}
return 0 ;
}