题解 P4171 [JSOI2010]满汉全席

Posted 章鱼那个哥

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解 P4171 [JSOI2010]满汉全席相关的知识,希望对你有一定的参考价值。

(Descripion:)

给出 (n) 种材料,有 (m) 个人,每个人会要求对某种材料进行汉式和满式两种加工。

一种材料只能用一次,问是否有可能满足全部人的要求。(满足定义是有一项他提出的菜做了)。

(Sample) (Input:)

2
3 4
m3 h1
m1 m2
h1 h3
h3 m2
2 4
h1 m2
m2 m1
h1 h2
m1 h2

(Sample) (Output:)

GOOD
BAD

(Solution:)

这种题有两种状态,只能在这两种状态里选,并且有限制,很明显是 (2-SAT) 的题。

考虑把满和汉两种烹饪分成两种状态,连边其实就是 或运算 连边

也就是如果这个点不选,那另一个肯定得选,如果另一个不选,那这个就就得选。

#include<bits/stdc++.h>
using namespace std;
int n,m,k,En,num,cnt,top;
const int N=205,M=2005;
int scc[N+N],head[N+N],dfn[N+N],low[N+N];
int s[N+N],ins[N+N];
char s1[10],s2[10];
struct edge {
    int next,to;
}E[M<<1];
inline void Get(int &a,int &b){
    char ch=getchar();
    while(ch!='h' && ch!='m') ch=getchar();
    a=(ch=='h');
    scanf("%d",&b);
}
inline void add(int from,int to){
    E[++En].next=head[from];
    E[En].to=to;
    head[from]=En;
} 
inline void tarjan(int u){
    dfn[u]=low[u]=++num;
    ins[u]=1;
    s[++top]=u;
    for(int i=head[u];i;i=E[i].next){
        int v=E[i].to;
        if(!dfn[v]){
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(ins[v])
            low[u]=min(low[u],dfn[v]);
    }
    if(dfn[u]==low[u]){
        scc[u]=++cnt;
        ins[u]=0;
        while(s[top]!=u){
            ins[s[top]]=0;
            scc[s[top]]=cnt;
            top--;
        }
        top--;
    }
}
inline bool two_sat(){
    for(int i=1;i<=n;++i)
        if(scc[i]==scc[i+n]) return false;
    return true;
}
int main(){
    scanf("%d",&k);
    while(k--){
        num=cnt=En=0;
        memset(scc,0,sizeof(scc));
        memset(head,0,sizeof(head));
        memset(dfn,0,sizeof(dfn));
        memset(low,0,sizeof(low));
        memset(E,0,sizeof(E));
        memset(ins,0,sizeof(ins));
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;++i){
            int ax=0,ay=0;
            int bx=0,by=0;
            Get(ax,ay);
            Get(bx,by);
            add(ay+(!ax)*n,by+n*bx);
            add(by+(!bx)*n,ay+n*ax);
        }
        for(int i=1;i<=n+n;++i)
            if(!dfn[i]) tarjan(i);
        if(two_sat()) puts("GOOD");
        else puts("BAD");
    }
    return 0;
}

以上是关于题解 P4171 [JSOI2010]满汉全席的主要内容,如果未能解决你的问题,请参考以下文章

题解JSOI2010满汉全席

BZOJ1823 [JSOI2010]满汉全席 2-sat

2-SAT[JSOI2010]满汉全席

luoguP4171 [JSOI2010]满汉全席

[JSOI 2010] 满汉全席

BZOJ1823: [JSOI2010]满汉全席(2-sat)