POJ 2912 Rochambeau(路径压缩并查集)
来源:互联网 发布:只有域名怎么绑定微博 编辑:程序博客网 时间:2024/05/17 03:30
POJ 2912 Rochambeau(路径压缩并查集)
http://poj.org/problem?id=2912
题意:
有n(n<=500)个小孩玩游戏,里面有一个人是裁判,剩下的人分为三组(一组固定出石头,一组固定出剪子,一组固定出布,但是可能有某组为空)。现在我们既不知道裁判是谁也不知道分组的情况。现在n个小孩玩剪刀石头布,已知每组的小孩只会出同一种手势,但是裁判出的手势是随机的,所以现在给出你M次两个小孩之间的游戏结果,问你是否能判断出谁是裁判,如果能的话就输出对应的信息。
分析:
由于N<=500,所以我们依次假设第i个小孩是裁判,然后通过比赛的结果来判断第i个小孩是否可能为裁判。
如何判断第i个小孩是不是裁判呢?
假设第i个小孩是裁判,那么他出拳是随机的,所以只要有他参与的比赛我们自动忽略。然后剩下的两两比赛就是路基压缩并查集的一个个关系了,我们按照路径压缩并查集的做法看看剩下的比赛是否存在冲突。如果有冲突,那么i小孩不能是裁判。如果没冲突,i小孩能做裁判。
经过N轮枚举,我们能得到共有X个小孩可以做裁判,如果:
X==0,说明 Impossible
X>1,说明Can not determine
X==1时,输出那个裁判的编号 且输出其他所有小孩的第一条冲突发生语句的位置 最大值Y,即通过前Y条语句我们就能知道N-1个小孩都不可能是裁判(虽然此为Accept代码解法,但此处我个人认为有问题。因为就算你通过前Y条关系知道前N-1个小孩不可能是裁判,但是你还是需要看第N个小孩的枚举情况,看完第N个小孩的最后一条语句才能知道第N个小孩是否可以做裁判吧,说不定正好最后一条语句发生冲突呢?)。
枚举裁判,每个非裁判的小孩是并查集的一个节点。如果a->b==0,那么表示a与b同类。a->b==1,那么表示a吃b(比如a为剪子的时候,b为布)。a->b==2,那么表示a被b吃(比如a为布的时候,b为剪子)。
剩下的就是类似食物链POJ1182的解法分析了。记得此时忽略你假设为裁判的所有语句。
AC代码:
#include<cstdio>#include<cstring>#include<algorithm>#include<vector>using namespace std;const int MAXN=500+100;const int MAXM=2000+100;int F[MAXN];//父节点int v[MAXN];//v[i]=x表示节点i与其父节点的大小关系int findset(int i){ if(F[i]==-1)return i; int temp = findset(F[i]); v[i] += v[F[i]]; v[i]%=3; return F[i]=temp;}void bind(int i,int j,int temp){ int fa= findset(i); int fb= findset(j); if(fa!=fb) { F[fb]=fa; v[fb]=(v[i]-temp-v[j]+3*3)%3; }}struct command{ int a,temp,b;} coms[MAXM];bool judge[MAXN];//judge[i]=true 表示i可以作为裁判int pos[MAXN];//保存在第几步可判断i是裁判int main(){ int n,m; while(scanf("%d%d",&n,&m)==2) { for(int i=0; i<m; i++) { char c; scanf("%d%c%d",&coms[i].a,&c,&coms[i].b); if(c=='=') coms[i].temp=0; else if(c=='>') coms[i].temp=1; else if(c=='<') coms[i].temp=2; } memset(pos,-1,sizeof(pos));//pos[i]=x表示i作为裁判的时候,第x位置会出问题,如果x=-1则表示i左裁判不会出问题 memset(judge,1,sizeof(judge)); for(int i=0; i<n; i++) //假设i为裁判 { memset(F,-1,sizeof(F)); memset(v,0,sizeof(v)); for(int j=0; j<m; j++) { int a,b,temp; a=coms[j].a; b=coms[j].b; temp=coms[j].temp; if( (a==i||b==i) )//有关i的命令都跳过 continue; else//ab不含裁判i { int fa=findset(a); int fb=findset(b); if(fa==fb)//同一分量 { if( (v[b]+temp)%3!=v[a] )//不合法 { judge[i]=false; pos[i]=j+1; //printf("pos[%d]=%d\n",i,j); break; } } else//不同连通分量 { bind(a,b,temp); } } } } int tot=0;//记录有多少个裁判 int judge_i; int max_p=0;//所有出错裁判的最大错误位置 for(int i=0; i<n; i++) { if(judge[i])//i可以作为裁判 { tot++; judge_i=i; } else max_p=max(max_p,pos[i]);//找到所有出错裁判的最大错误位置 } if(tot==0) printf("Impossible\n"); else if(tot==1) printf("Player %d can be determined to be the judge after %d lines\n",judge_i,max_p); else if(tot>1) printf("Can not determine\n"); } return 0;}
- POJ 2912 Rochambeau(路径压缩并查集)
- poj 2912 - Rochambeau(并查集)
- poj 2912 Rochambeau(暴力+并查集)
- Poj-2912 Rochambeau 枚举+并查集
- POJ 2912 Rochambeau 并查集+枚举
- POJ-2912-Rochambeau [并查集][枚举]
- POJ 2912 Rochambeau(枚举+并查集)
- POJ 2912 Rochambeau(枚举+带权并查集)
- poj 2912 Rochambeau(带权并查集 + 暴力)
- poj 2912 Rochambeau【枚举+种类并查集】
- POJ 2912 Rochambeau(枚举 + 偏移量并查集)
- poj 2912 Rochambeau(带权并查集)
- POJ - 2912 Rochambeau(带权并查集+暴力)
- POJ 2912 Rochambeau(枚举+加权并查集)
- POJ 2912 Rochambeau(带权并查集)
- poj 1611 并查集 + 压缩路径
- 并查集-POJ2912 Rochambeau
- POJ 2912 Rochambeau【并查集经典应用同食物链+枚举】
- 死锁产生的原因及四个必要条件
- linux 守护进程
- 敏捷开发之道(八)设计
- 华为大牛的10年总结
- 代码分享站点
- POJ 2912 Rochambeau(路径压缩并查集)
- 错误:undefined reference to `__gxx_personality_v0' .
- Static块什么时候运行
- 进程入门之使用文件映射
- struct sockaddr_in 和 struct sockaddr
- 第一章:检索记录 20140314
- 一、spring mvc的获取参数和传递参数
- SQL调整数据的外观
- Maven内置隐式变量