题目来源:http://poj.org/problem?id=2912
★好久没写题了,又回到了并查集,发现并查集都没学好,写个锤子线段树
翻译:
有一群孩子在玩剪刀石头布游戏(真的是没看到剪刀石头布 半天不会写,一看到就明白了一二分)
一个人是裁判,其他的分为三组(可能有些组没人)
除了裁判可以变换着出,其他人都只能出固定的,并且同组的人是平局
然后给出m组胜负结果,让你判断能不能找到裁判
思路:
这题n和m的数量都不大,所以可以枚举哪个人是裁判来判断。
但是怎么处理人之间的关系呢?这里就用到了种类并查集~
我们不妨设
a>b 为 r=2
a<b 为r=1
a=b 为r=0
不难看出 a>b b>c 时 c>a 如果关系运算就是(2+2)%3=1 那么我们的定义就没问题
合并操作
a的父节点为p,b的父节点为q,a和p的关系式va,b和q的关系式vb,并且a和b的关系式r
那么把他们看作向量可知:va+vp-vb=r 故vp=(vb+r-va+3)%3
即val[p]=(val[f[j].t]+f[j].r-val[f[j].s]+3)%3;
路径压缩就不说了~
代码:
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<string>
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
using namespace std;
const int maxn=5e2+5;
const int sz=1<<10;
const int mod=1e9+7;
const int inf=2e9;
const double eps=1e-8;
const double pi=acos(-1);
typedef long long LL;
int n,m;
char s[120];
struct node
{
int s,t;
int r;
}f[maxn<<3];
int dad[maxn];
int val[maxn];
template<class t>
inline void read(t &x)
{
char c; x=1;
while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
t res=c-'0';
while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
x*=res;
}
int seek(int k)
{
if(k==dad[k]) return k;
int tmp=seek(dad[k]);
val[k]=(val[k]+val[dad[k]])%3;
return dad[k]=tmp;
}
int main()
{
while(~scanf("%d%d",&n,&m)){
getchar();
for(int i=1;i<=m;i++){
gets(s);
int mid,len=strlen(s);
for(int j=0;j<len;j++){
if(s[j]=='>'||s[j]=='<'||s[j]=='='){
mid=j;
break;
}
}
f[i].s=f[i].t=0;
for(int j=0;j<mid;j++){
f[i].s=f[i].s*10+s[j]-'0';
}
for(int j=mid+1;j<len;j++){
f[i].t=f[i].t*10+s[j]-'0';
}
f[i].s++; f[i].t++;
if(s[mid]=='>') f[i].r=2;
else if(s[mid]=='<') f[i].r=1;
else f[i].r=0;
// cout<<f[i].s<<' '<<f[i].t<<' '<<f[i].r<<endl;
}
for(int i=1;i<=m;i++){
// cout<<f[i].s<<' '<<f[i].t<<' '<<f[i].r<<endl;
}
int cnt=0;
int round=0,who;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
dad[j]=j;
val[j]=0;
}
int flag=-1;
for(int j=1;j<=m;j++){
if(f[j].s==i||f[j].t==i) continue;
int p=seek(f[j].s),q=seek(f[j].t);
if(p==q){
if((val[f[j].s]-val[f[j].t]+3)%3!=f[j].r){
flag=j;
break;
}
}
else{
dad[p]=q;
val[p]=(val[f[j].t]+f[j].r-val[f[j].s]+3)%3;
}
}
if(flag==-1){
cnt++;
who=i-1;
}
else round=max(round,flag);
}
if(cnt==0) cout<<"Impossible\n";
else if(cnt==1) printf("Player %d can be determined to be the judge after %d lines\n",who,round);
else cout<<"Can not determine\n";
}
return 0;
}