题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1823
我做的第一道2-SAT裸题。不得不说题目描述看起来比NOI2002银河英雄传说都可怕。。。注意图是有向的。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <stack>
using namespace std;
const int N=2005,M=20005,inf=0x3fffffff;
int head[N],ver[M<<1],next[M<<1];
int dfn[N],low[N],bel[N],q[N<<1],m,n,scc;
bool inq[N];
int tot=1,t=0,T,top=0;
void add (int u,int v) {
ver[++tot]=v;next[tot]=head[u];head[u]=tot;
}
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int get () {
int x;
char c=getchar();
while (c!='m'&&c!='h') c=getchar();
if (c=='m') x=read()*2;
else x=read()*2+1;
return x;
}
void Tarjan (int x) {
dfn[x]=low[x]=++t;
q[++top]=x;inq[x]=1;
for (int i=head[x];i;i=next[i])
if (!dfn[ver[i]]) {
Tarjan(ver[i]);
low[x]=min(low[x],low[ver[i]]);
}
else if (inq[ver[i]])
low[x]=min(low[x],dfn[ver[i]]);
if (low[x]==dfn[x]) {
scc++;
int now=0;
while (now!=x) {
now=q[top--];
bel[now]=scc;
inq[now]=0;
}
}
}
int main () {
T=read();
while (T--) {
memset(head,0,sizeof(head));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(bel,0,sizeof(bel));
memset(inq,0,sizeof(inq));
tot=1,t=m=n=scc=top=0;
n=read(); m=read();
int x,y,xp,yp;
for (int i=1;i<=m;i++) {
x=get(); y=get();
xp=x^1;yp=y^1;
add(xp,y);add(yp,x);
}
bool flag=0;
for (int i=2;i<=2*n+1;i++)
if (!dfn[i]) Tarjan(i);
for (int i=1;i<=n;i++)
if (bel[2*i]==bel[2*i+1])
{ puts("BAD");flag=1;break; }
if (!flag) puts("GOOD");
}
return 0;
}