bzoj 1823: [JSOI2010]满汉全席

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值