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; }