第一次想到的是枚举每个人是裁判然后判断谁是裁判的话剩下几个人的关系不矛盾,
然后满足情况的裁判个数是0矛盾,大于一多组解这点想的是对的
然后打算再跑一遍并查集然后求第二个矛盾且包含唯一裁判的条件即为答案一直wa。。。。
因为带权并查集是维护一些有特定关系的点,然而裁判和别人的关系是不固定的所以不能一起加入并查集
然后贪心 让你判断能找出裁判的最少条件 = 判断出别人不是裁判的最少条件
那就是跑n遍并查集找出其中假设每个人为裁判的下标最小的矛盾条件中的最大值
因为假设每个人为裁判当判断出这种情况不行的时候就不需要再判断了
当把所有其他人都判断出不是裁判的时候结果就出来了所以要取最大值
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define maxn 550
using namespace std;
int fa[maxn],va[maxn],n,m,ju;
char c;
int dis[505],po;
int getFa(int i)
{
if(i==fa[i])return i;
int pre = fa[i];
fa[i] = getFa(fa[i]);
va[i] = (va[i]+va[pre])%3;
return fa[i];
}
struct node{
int a,b;
char c;
}no[maxn*5];
bool ok(int ju)
{
for(int i=0;i<n;i++){fa[i] = i,va[i] = 0;}
for(int i=0;i<m;i++)
if(no[i].a!=ju&&no[i].b!=ju)
{
int flag,a=no[i].a,b = no[i].b;
if(no[i].c=='=')flag = 0;
else if(no[i].c=='<')flag = 1;
else flag = 2;
int faa = getFa(no[i].a),fab = getFa(no[i].b);
if(faa!=fab)
{
fa[fab] = faa;
va[fab] = ((3-va[b])%3+va[a]+(3-flag)%3)%3;
}
else if((va[a]+(3-va[b])%3)%3!=flag){po = max(po,i+1);return false;}
}
return true;
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
int sum = 0;
ju = 0;
po = 0;
for(int i=0;i<m;i++)
{
scanf("%d",&no[i].a);
scanf("%c",&no[i].c);
while(no[i].c==' ') scanf("%c",&no[i].c);
scanf("%d",&no[i].b);
}
for(int i=0;i<n;i++)
if(ok(i)){sum++;ju = i;}
if(sum>1)printf("Can not determine\n");
else if(sum==0)printf("Impossible\n");
else printf("Player %d can be determined to be the judge after %d lines\n",ju,po);
}
return 0;
}