#2-sat,Tarjan#洛谷 4171 [JSOI2010]满汉全席
分析
考虑两个至少选一个就是非A即B,非B即A,
都可行当且仅当A与非A不在同一个强连通分量里
代码
#include <cstdio>
#include <cctype>
#include <cstring>
#include <stack>
#define rr register
using namespace std;
const int N=211; stack<int>stac; struct node{int y,next;}e[N*10];
int as[N],dfn[N],low[N],v[N],col[N],n,m,et,flag,tot,cnt; char ch;
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline void add(int x,int y){e[++et]=(node){y,as[x]},as[x]=et;}
inline signed min(int a,int b){return a<b?a:b;}
inline void tarjan(int x){
dfn[x]=low[x]=++tot,
v[x]=1,stac.push(x);
for (rr int i=as[x];i;i=e[i].next)
if (!dfn[e[i].y]){
tarjan(e[i].y);
low[x]=min(low[x],low[e[i].y]);
}else if (v[e[i].y])
low[x]=min(low[x],dfn[e[i].y]);
if (dfn[x]==low[x]){
rr int y; ++cnt;
do{
y=stac.top(),stac.pop(),
v[y]=0,col[y]=cnt;
}while (x^y);
}
}
signed main(){
for (rr int T=iut();T;--T){
memset(dfn,0,sizeof(dfn)),
memset(low,0,sizeof(low)),
memset(as,0,sizeof(as));
n=iut(),et=flag=1,tot=cnt=0;
for (rr int m=iut();m;--m){
rr int f1,f2,x,y;
for (ch=getchar();!isalpha(ch);ch=getchar());
if (ch=='m') f1=1; else f1=0; x=iut();
for (ch=getchar();!isalpha(ch);ch=getchar());
if (ch=='m') f2=1; else f2=0; y=iut();
add(x+(f1^1)*n,y+f2*n),add(y+(f2^1)*n,x+f1*n);
}
for (rr int i=1;i<=n*2;++i)
if (!dfn[i]) tarjan(i);
for (rr int i=1;i<=n;++i)
if (col[i]==col[i+n]) flag=0;
puts(flag?"GOOD":"BAD");
}
return 0;
}