[NOI2002] 银河英雄传说

题目链接:###

点我

题目分析:###

带权并查集的题,记一个\(d\)数组维护每个战舰前面有多少战舰,再在每个树根上记录一个集合大小\(sum\),每次进行\(get_father\)的时候维护一下\(d\)数组,合并的时候更新集合大小。由于写了路径压缩,每次合并的时候还要把之前集合的\(sum\)更新到\(d\)数组上。

代码:###

#include<bits/stdc++.h>
#define N (1000000+5)
using namespace std;
inline int read(){
	int cnt=0,f=1;char c;
	c=getchar();
	while(!isdigit(c)){
		if(c=='-') f=-f;
		c=getchar();
	}
	while(isdigit(c)){
		cnt=cnt*10+c-'0';
		c=getchar();
	}
	return cnt*f;
}

int t,fa[N],d[N],sum[N],x,y;
char c;

int get_father(int x){
	if(fa[x]==x)return x;
	int root=get_father(fa[x]);
	d[x]+=d[fa[x]];
	return fa[x]=root;
}

void merge(int x,int y){
	int a=get_father(x);
	int b=get_father(y);
	fa[a]=b;d[a]=sum[b];
	sum[b]+=sum[a];
}

int query(int x,int y){
	int a=get_father(x);
	int b=get_father(y);
	if(a!=b) return -1;
	else {
	int ans=abs(d[x]-d[y])-1;
	return ans;
	}
}

int main(){
	t=read();
	for(register int i=1;i<=30001;i++) fa[i]=i,d[i]=0,sum[i]=1;
	for(register int i=1;i<=t;i++) {
		cin>>c;x=read();y=read(); 
		if(c=='M') merge(x,y);
		if(c=='C') printf("%d\n",query(x,y));
	}
	return 0;
}
posted @ 2019-01-28 00:29  kma_093  阅读(246)  评论(0编辑  收藏  举报