poj 1703
2015-09-17 19:14
267 查看
经典的并查集问题。
我们可以有两种做法:
第一种是我们用一个数组vis[i]=j来表示i的敌人是j,那么我们在知道a,b是敌人之后,那么如果vis[a]有值的话,vis[a]和b是一伙的,如果vis[b]的有值的话,vis[b]和a是一伙的。所以这样判断即可。
第二种做法是使得整个并查集有个偏移量,即如果a和b是敌人,那么我们假设a和b+M是一伙的,这样子如果find(a)==find(b),说明是一伙的,如果find(a) == find(b+M),那么a和b是敌人。
我们拿例子来看,
1,2是敌人,那么1,2+M是一伙的,2,1+M是一伙的。
2,4是敌人,那么2,4+M是一伙的,4,2+M是一伙的。
从上面可以看出,1和4就是一伙的,因为它们有个共同的“虚拟伙伴”2+M。
我们可以有两种做法:
第一种是我们用一个数组vis[i]=j来表示i的敌人是j,那么我们在知道a,b是敌人之后,那么如果vis[a]有值的话,vis[a]和b是一伙的,如果vis[b]的有值的话,vis[b]和a是一伙的。所以这样判断即可。
#include<stdio.h> #include<iostream> #include<string> #include<string.h> #include<algorithm> #include<iomanip> #include<vector> #include<time.h> #include<queue> #include<stack> #include<iterator> #include<math.h> #include<stdlib.h> #include<limits.h> #include<map> #include<set> #include<bitset> //#define ONLINE_JUDGE #define eps 1e-5 #define INF 0x7fffffff #define FOR(i,a) for((i)=0;i<(a);(i)++) #define MEM(a) (memset((a),0,sizeof(a))) #define sfs(a) scanf("%s",a) #define sf(a) scanf("%d",&a) #define sfI(a) scanf("%I64d",&a) #define pf(a) printf("%d\n",a) #define pfI(a) printf("%I64d\n",a) #define pfs(a) printf("%s\n",a) #define sfd(a,b) scanf("%d%d",&a,&b) #define sft(a,b,num) scanf("%d%d%d",&a,&b,&num) #define for1(i,a,b) for(int i=(a);i<b;i++) #define for2(i,a,b) for(int i=(a);i<=b;i++) #define for3(i,a,b)for(int i=(b);i>=a;i--) #define MEM1(a) memset(a,0,sizeof(a)) #define MEM2(a) memset(a,-1,sizeof(a)) #define ll __int64 const double PI=acos(-1.0); template<class T> T gcd(T a,T b){return b?gcd(b,a%b):a;} template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;} template<class T> inline T Min(T a,T b){return a<b?a:b;} template<class T> inline T Max(T a,T b){return a>b?a:b;} using namespace std; //#pragma comment(linker,"/STACK:1024000000,1024000000") int n,m,d; #define N 200005 #define M 100010 #define Mod 1000000000 #define p(x,y) make_pair(x,y) const int MAX_len=550; int fa[M]; int vis[M]; int findfa(int x){ return x==fa[x]?fa[x]:fa[x]=findfa(fa[x]); } void Union(int x,int y){ int fx = findfa(x); int fy = findfa(y); if(fx!=fy){ if(fx<fy) fa[fy] = fx; else fa[fx] = fy; } } int main(){ #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); // freopen("out.txt", "w", stdout); #endif int t; sf(t); while(t--){ sfd(n,m); char op[2]; int a,b; for(int i=0;i<M;i++) fa[i]=i; memset(vis,0,sizeof vis); for(int i=0;i<m;i++){ scanf("%s%d%d",op,&a,&b); if(op[0] == 'A'){ if(findfa(a) == findfa(b)) printf("In the same gang.\n"); else if(findfa(a) == findfa(vis[b])) //a和b的敌人是一伙的,那么a,b不是一伙的 printf("In different gangs.\n"); else printf("Not sure yet.\n"); }else{ if(!vis[a] && !vis[b]){ //a,b都没有值 vis[a] = b; vis[b] =a; } else if(!vis[a]){ //b有值,说明a和vis[b]是一伙的 vis[a] = b; Union(a,vis[b]); } else if(!vis[b]){ //a有值,说明b和vis[a]是一伙的 vis[b] = a; Union(b,vis[a]); }else{ //都有值,说明a和vis[b]、b和vis[a]是一伙的 Union(a,vis[b]); Union(b,vis[a]); } } } } return 0; }
第二种做法是使得整个并查集有个偏移量,即如果a和b是敌人,那么我们假设a和b+M是一伙的,这样子如果find(a)==find(b),说明是一伙的,如果find(a) == find(b+M),那么a和b是敌人。
我们拿例子来看,
1,2是敌人,那么1,2+M是一伙的,2,1+M是一伙的。
2,4是敌人,那么2,4+M是一伙的,4,2+M是一伙的。
从上面可以看出,1和4就是一伙的,因为它们有个共同的“虚拟伙伴”2+M。
#include<stdio.h> #include<iostream> #include<string> #include<string.h> #include<algorithm> #include<iomanip> #include<vector> #include<time.h> #include<queue> #include<stack> #include<iterator> #include<math.h> #include<stdlib.h> #include<limits.h> #include<map> #include<set> #include<bitset> //#define ONLINE_JUDGE #define eps 1e-5 #define INF 0x7fffffff #define FOR(i,a) for((i)=0;i<(a);(i)++) #define MEM(a) (memset((a),0,sizeof(a))) #define sfs(a) scanf("%s",a) #define sf(a) scanf("%d",&a) #define sfI(a) scanf("%I64d",&a) #define pf(a) printf("%d\n",a) #define pfI(a) printf("%I64d\n",a) #define pfs(a) printf("%s\n",a) #define sfd(a,b) scanf("%d%d",&a,&b) #define sft(a,b,num) scanf("%d%d%d",&a,&b,&num) #define for1(i,a,b) for(int i=(a);i<b;i++) #define for2(i,a,b) for(int i=(a);i<=b;i++) #define for3(i,a,b)for(int i=(b);i>=a;i--) #define MEM1(a) memset(a,0,sizeof(a)) #define MEM2(a) memset(a,-1,sizeof(a)) #define ll __int64 const double PI=acos(-1.0); template<class T> T gcd(T a,T b){return b?gcd(b,a%b):a;} template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;} template<class T> inline T Min(T a,T b){return a<b?a:b;} template<class T> inline T Max(T a,T b){return a>b?a:b;} using namespace std; //#pragma comment(linker,"/STACK:1024000000,1024000000") int n,m,d; #define N 200005 #define M 100010 #define Mod 1000000000 #define p(x,y) make_pair(x,y) const int MAX_len=550; int fa[2*M]; int findfa(int x){ return x==fa[x]?fa[x]:fa[x]=findfa(fa[x]); } void Union(int x,int y){ int fx = findfa(x); int fy = findfa(y); if(fx!=fy){ if(fx<fy) fa[fy] = fx; else fa[fx] = fy; } } int main(){ #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); // freopen("out.txt", "w", stdout); #endif int t; sf(t); while(t--){ sfd(n,m); char op[2]; int a,b; for(int i=0;i<M*2;i++) fa[i]=i; for(int i=0;i<m;i++){ scanf("%s%d%d",op,&a,&b); if(op[0] == 'A'){ if(findfa(a) == findfa(b)) printf("In the same gang.\n"); else if(findfa(a) == findfa(b+M)) printf("In different gangs.\n"); else printf("Not sure yet.\n"); }else{ Union(a,b+M); Union(b,a+M); } } } return 0; }
相关文章推荐
- CSS3文本溢出
- Android推荐书目文章(实时更新....)
- 算法导论 使用两个队列实现一个栈
- UIday1801:沙盒三个文件的路径的获取、简单与复杂对象的读写、NSUserDefaults、NSFileManager
- 美团霸面---我想说说心里话。
- 【转】android fragment 博客 学习
- machine learning(12) -- classification: One-vs-all classfication
- 如何利用 JConsole观察分析Java程序的运行,进行排错调优
- 面向对象编程,类切换
- Rsa私钥生成
- 解析Linux内核获取当前进程指针的方法
- 逻辑问题:汉诺塔
- 【SDUTOJ 3323】 园艺问题 (离散化+线段树+离线数据处理)
- 如何使用Ubuntu打电话
- python日积月累之None和设置编码
- java学习之Map集合
- 2609HDU
- 字符串的最小表示法和最大表示法
- 关于数据结构的学习经验分享 (1关于实现语言)
- 表达式左值右值