【CDOJ】爱吃瓜的伊卡洛斯(2)

L - 爱吃瓜的伊卡洛斯(2)

Time Limit: 1000 MS     Memory Limit: 64 MB
Submit Status

伊卡洛斯很爱吃西瓜。一次,他来到一个西瓜摊旁,发现水果摊有$N$个西瓜,西瓜有红色、黄色、绿色、蓝色……等等数不清的颜色。 伊卡洛斯很想知道知道一些信息,便于老板交谈了起来。 当老板的话的第一个字符为”A”时,老板会告诉伊卡洛斯一些信息,格式如下: $A\ x\ y\ 1$ 这句话表示第$x$个西瓜和第$y$个西瓜是同一种颜色的。 $A\ x\ y\ 2$ 这句话表示第$x$个西瓜和第$y$个西瓜是不同种颜色的。

当然,为了考验伊卡洛斯有没有认真听, 老板也会时不时问伊卡洛斯一些问题,格式如下: $Q\ x\ y$ 这句话表示询问第$x$个西瓜和第$y$个西瓜是不是同一种颜色,如果确定为同一种颜色,伊卡洛斯需要回答1;确定为不同种颜色,伊卡洛斯需要回答2;无法确定时伊卡洛斯回答3。 注意,伊卡洛斯是根据已获得的信息来回答的。也就是只有这个问题之前的信息才为已知信息。

老板说,只有回答对他全部的问题,伊卡洛斯才能吃到瓜,他聪明的想到了让你来帮助他。

Input

第一行包含两个整数$N$和$M$,$N$是西瓜总数,$M$是以$A$或$Q$开头的老板的话总和。
以下$M$行,每行包含一条老板的话。形式有$A\ x\ y\ 1$或$A\ x\ y\ 2$或$Q\ x\ y$。 $1 \le N \le 100000\ 1 \le M \le 200000\ 1 \le X, Y \le N$ 数据保证没有矛盾

Output

对于每一条$Q$指令,输出1/2/3代表两个西瓜颜色的关系。

Sample input and output

Sample Input Sample Output
6 9  
A 1 2 1  
A 1 3 1  
A 1 4 2  
Q 2 4  
Q 1 6  
A 3 6 1  
A 4 5 2  
Q 1 5  
Q 1 6
2
3
3  
1

Hint

西瓜的颜色可以有无数多种!

#include<bits/stdc++.h>
using namespace std;

 
int fa[200005];
set<int> s[200005];

int get(int x)
{
	if(fa[x]==x) return x;
	return fa[x]=get(fa[x]); 
}

void merge(int x, int y)
{
	int fx = get(x);
	int fy = get(y);
	if(fx!=fy)
	{
		if(s[fx].size()>s[fy].size())	swap(fx,fy);
		fa[fx]=fy;
		if(s[fx].size())
		{
			set<int>::iterator it;
			for(it= s[fx].begin();it!=s[fx].end();it++)
			{
				int tmp = *it;
				s[fy].insert(get(tmp));
				
			}
		}
	}
}

int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)	fa[i]=i;
	while(m--)
	{
		char op[3];
		scanf("%s",op);
		if(op[0]=='A')
		{	
			int x,y,z;
			
			scanf("%d%d%d",&x,&y,&z);
			if(z==1)
			{
				merge(x,y);
			}
			else
			{
				s[get(x)].insert(get(y));
				s[get(y)].insert(get(x));
			}
		}
		else
		{
			int x,y;
			
			scanf("%d%d",&x,&y);
			if(get(x)==get(y))
			{
				printf("1\n");
			}
			else if(s[get(x)].find(get(y))!=s[get(x)].end()||s[get(y)].find(get(x))!=s[get(y)].end())
			{
				printf("2\n");
			 } 
			else
			{
				printf("3\n");
			}
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/michaelliu6/article/details/80369528