很简单的2-SAT.。。我一开始觉得题目好长啊然后感觉好像就是个模板题结果我直接套模板真就过了。。
就是模板。
至于连边跟模板一样是因为如果最优方案,一个评委明显只能满足两个中的一个(重复不算)。
#include<cstdio>
#include<algorithm>
#include<cstring>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int N=5e5+5;
int n,m;
int a[N],b[N],head[N],next[N],go[N];
bool ins[N];
int low[N],dfn[N],stk[N];
int top,tim,bl,tot,block[N];
inline void tarjan(int x)
{
dfn[x]=low[x]=++tim;
stk[++top]=x;
ins[x]=1;
for(int i=head[x];i;i=next[i])
{
int v=go[i];
if (!dfn[v])
{
tarjan(v);
low[x]=min(low[x],low[v]);
}
else if (ins[v])low[x]=min(dfn[v],low[x]);
}
if (dfn[x]==low[x])
{
bl++;
int j=0;
while (j!=x)
{
j=stk[top--];
block[j]=bl;
ins[j]=0;
}
}
}
inline bool jud()
{
fo(i,1,n)
if (block[2*i]==block[2*i-1])return 0;
return 1;
}
inline void add(int x,int y)
{
go[++tot]=y;
next[tot]=head[x];
head[x]=tot;
}
int main()
{
int cas;
scanf("%d",&cas);
while (cas--)
{
memset(head,0,sizeof(head));
memset(dfn,0,sizeof(dfn));
tot=bl=tim=top=0;
scanf("%d%d",&n,&m);
fo(i,1,m)
{
int x,y,numx,numy;
char x1=getchar();
while(x1!='h'&&x1!='m')x1=getchar();
scanf("%d",&x);x*=2;
if (x1=='h')x=x-1;
char y1=getchar();
while(y1!='h'&&y1!='m')y1=getchar();
scanf("%d",&y);y*=2;
if (y1=='h')y=y-1;
if (x%2==0)numx=x--;
else numx=x++;
if (y%2==0)numy=y--;
else numy=y++;
add(numx,y);
add(numy,x);
}
fo(i,1,2*n)if (!dfn[i])tarjan(i);
if (jud())puts("GOOD");
else puts("BAD");
}
}