题目描述
算了太长了,就不复制了
Solution
对于每种食材,只有HM两种选择
考虑2-SAT,对于每种限制条件就相当于X or Y = 1.
建边就是X’->Y, Y’->X
第一次写2-SAT感觉还不错
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 100010
inline int read(){
int ret=0,ff=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='h') ff=-ff;
ch=getchar();
}
while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
return ret*ff;
}
int ts(int a){
return a>0?a<<1|1:((~a)+1)<<1;
}
struct Edge{
int u,v,next;
}E[maxn];
int head[maxn],ecnt=0,low[maxn],ins[maxn],stk[maxn],top,dfn[maxn],ord,cnt,blg[maxn];
void addedge(int u,int v){
E[++ecnt].u=u;
E[ecnt].v=v;
E[ecnt].next=head[u];
head[u]=ecnt;
}
void Tarjan(int x){
low[x]=dfn[x]=++ord;
stk[++top]=x,ins[x]=1;
for(int i=head[x];i;i=E[i].next){
int v=E[i].v;
if(dfn[v]==0) Tarjan(v),low[x]=min(low[x],low[v]);
else if(ins[v]) low[x]=min(low[x],dfn[v]);
}
if(low[x]==dfn[x]){
++cnt;
int tmp;
do{
tmp=stk[top--];
ins[tmp]=0;
blg[tmp]=cnt;
}while(tmp!=x);
}
}
bool ck(int n){
for(int i=2;i<=n;i+=2){
if(blg[i]==blg[i^1]) return 0;
}
return 1;
}
void init(int n){
for(int i=0;i<=n;++i)
head[i]=ins[i]=blg[i]=dfn[i]=low[i]=stk[i]=0;
// memset(E,0,sizeof(E));
ecnt=top=cnt=ord=0;
}
int main(){
//freopen("bzoj1823.in","r",stdin);
int T=read();
while(T--){
int n=read(),m=read();
for(int i=1;i<=m;++i){
int aa=ts(read()),bb=ts(read());
addedge(aa^1,bb),addedge(bb^1,aa);
}
for(int i=2;i<=(n<<1|1);++i){
if(dfn[i]==0)Tarjan(i);
}
if(ck(n<<1|1)) puts("GOOD");
else puts("BAD");
init(n<<1|1);
}
}