当前位置: 代码迷 >> 综合 >> bzoj 1823: [JSOI2010]满汉全席
  详细解决方案

bzoj 1823: [JSOI2010]满汉全席

热度:37   发布时间:2023-10-29 13:36:51.0

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;
}