#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;
}
posted @ 2020-11-03 20:43  lemondinosaur  阅读(57)  评论(0编辑  收藏  举报