首页 > 代码库 > poj 1703 Find them, Catch them(种类并查集和一种巧妙的方法)
poj 1703 Find them, Catch them(种类并查集和一种巧妙的方法)
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 36176 | Accepted: 11090 |
Description
Assume N (N <= 10^5) criminals are currently in Tadu City, numbered from 1 to N. And of course, at least one of them belongs to Gang Dragon, and the same for Gang Snake. You will be given M (M <= 10^5) messages in sequence, which are in the following two kinds:
1. D [a] [b]
where [a] and [b] are the numbers of two criminals, and they belong to different gangs.
2. A [a] [b]
where [a] and [b] are the numbers of two criminals. This requires you to decide whether a and b belong to a same gang.
Input
Output
Sample Input
1 5 5 A 1 2 D 1 2 A 1 2 D 2 4 A 1 4
Sample Output
Not sure yet. In different gangs.In the same gang.
题意:是一个城市有两个帮派,A 1 2是询问1和2这两个人是不是一个帮派,D 1 2是这两个人不在一个帮派 每一次A就输出一次 思路: 带权并查集,加一个数组re[]表示子节点和其父节点的关系,是一个门派就是0。不是就是1 2015,7,27
#include<stdio.h> #include<iostream> #include<string.h> using namespace std; #define M 100100 int x[M],re[M]; void init() { for(int i=0;i<M;i++){ x[i]=i; re[i]=0; } } int find(int k) { int temp=x[k]; if(x[k]==k) return k; x[k]=find(x[k]); if(re[k]==re[temp])//假设和父节点是同类就存0 re[k]=0; else re[k]=1; return x[k]; } void merge(int a,int b,int fa,int fb) { x[fa]=fb; if(re[a]==re[b]) re[fa]=1; else re[fb]=0; } int main() { int t,n,m,i,a,b,fa,fb; char ch; scanf("%d",&t); while(t--){ init(); scanf("%d%d",&n,&m); while(m--){ cin>>ch; scanf("%d%d",&a,&b); fa=find(a); fb=find(b); if(ch==‘A‘){ if(fa!=fb){ printf("Not sure yet.\n"); continue; } if(re[a]==re[b]){ printf("In the same gang.\n"); continue; } else{ printf("In different gangs.\n"); } } else{ if(fa!=fb) merge(a,b,fa,fb); } } } return 0; } /* 还有一种巧妙方法:大神的解析。是poj食物链那道题的弱化。可见全部元素个数为2 * N,假设i表示属于帮派A。那么i + N表示属于帮派B。 每次输入两个家伙不在同一帮派的时候。就合并他们分属两个帮派的元素。
*/ #include<stdio.h> #include<iostream> #include<string.h> using namespace std; #define M 200200 int x[M]; void init() { for(int i=0;i<M;i++) x[i]=i; } int find(int k) { if(x[k]==k) return k; x[k]=find(x[k]);//压缩路径 return x[k]; } void merge(int a,int b) { int fa=find(a); int fb=find(b); if(x[a]!=x[b]) x[fa]=fb; } bool same(int a,int b) { return find(a)==find(b); } int main() { int t,n,m,i,a,b,fa,fb; char ch; scanf("%d",&t); while(t--){ init(); scanf("%d%d",&n,&m); while(m--){ cin>>ch; scanf("%d%d",&a,&b); if(ch==‘A‘){ if(same(a,b)){ printf("In the same gang.\n"); continue; } if(same(a,b+n)){ printf("In different gangs.\n"); } else{ printf("Not sure yet.\n"); continue; } } else{ merge(a,b+n);//a和b一定不在一个门派,就把a和b+n合并 merge(a+n,b);//同理 } } } return 0; }
poj 1703 Find them, Catch them(种类并查集和一种巧妙的方法)