2-SAT的大水题啊!
因为每一个材料只有两个可能,于是就很模型了啊。
模型是两个不可以都不选
模型二:两者(A,B)不能同时不取
那么选择了A’就只能选择B,选择了B’就只能选择A
连边A’→B,B’→A
于是就可以很愉快地做出这题啦!
#include<cstdio>
#include<cstring>
const int M=1005*2;
const int N=105*2;
int T;
int n,m;
int read ()
{
char ch=getchar();int x=0;
while (ch<'0'&&ch>'9') ch=getchar();
while (ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}
return x;
}
struct qq
{
int x,y,last;
}s[M];int num,last[N];//汉:x 满x+n
void init (int x,int y)
{
num++;
s[num].x=x;s[num].y=y;
s[num].last=last[x];
last[x]=num;
}
int dfn[N],low[N],belong[N],cnt,sta[N],lalal,shen;
bool in[N];
int mymin (int x,int y){return x<y?x:y;}
void dfs (int x)
{
dfn[x]=low[x]=++lalal;
sta[++cnt]=x;
in[x]=true;
for (int u=last[x];u!=-1;u=s[u].last)
{
int y=s[u].y;
if (dfn[y]==-1)
{
dfs(y);
low[x]=mymin(low[x],low[y]);
}
else if (in[y]) low[x]=mymin(dfn[y],low[x]);
}
if (low[x]==dfn[x])
{
shen++;
int now;
do
{
now=sta[cnt--];
belong[now]=shen;
in[now]=false;
}while (now!=x);
}
}
int main()
{
scanf("%d",&T);
while (T--)
{
num=0;memset(last,-1,sizeof(last));
scanf("%d%d",&n,&m);
for (int u=1;u<=m;u++)
{
char ch=getchar();int x,y;
while (ch!='m'&&ch!='h') ch=getchar();
x=read();
char ch1=getchar();
while (ch1!='m'&&ch1!='h') ch1=getchar();
y=read();
if (ch=='h'&&ch1=='h') {init(x+n,y);init(y+n,x); }
if (ch=='h'&&ch1=='m') {init(y,x); init(x+n,y+n);}
if (ch=='m'&&ch1=='m') {init(x,y+n);init(y,x+n); }
if (ch=='m'&&ch1=='h') {init(x,y); init(y+n,x+n);}
}
memset(dfn,-1,sizeof(dfn));
memset(in,false,sizeof(in));
shen=lalal=cnt=0;
for (int u=1;u<=2*n;u++)
if (dfn[u]==-1)
dfs(u);
bool tf=true;
for (int u=1;u<=n;u++)
if (belong[u]==belong[u+n])
{
tf=false;
break;
}
if (tf) printf("GOOD\n");
else printf("BAD\n");
}
return 0;
}