您的位置:首页 > 其它

ZOJ 3789 Gears (并查集 合并+删除+离根节点的距离)

2014-06-08 17:45 323 查看
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 ;
}

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 ;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: