BZOJ 1823 [JSOI2010]满汉全席

来源:互联网 发布:软件企业商业模式 编辑:程序博客网 时间:2024/04/27 19:48

好裸的一道题。
建边的思路,对于一个评委来说,设一个材料A选h,B选m,那么若A选m的话,B必须选m,B选h的话,A必须选h(因为两者之一要满足被选)

2-sat的关键思路就是找出一个被选,另一个必须被选的这样的约束关系。

还有就是注意下标!!!2~2n+1

#include<iostream>#include<cstring>#include<cstdlib>#include<cstdio>#include<algorithm>using namespace std;const int maxn=2005;struct edge{    int to,next;}e[maxn<<1];int cnt,n,m,T,scnt,scccnt,dfs_clock;int stack[maxn],dfn[maxn],low[maxn],head[maxn],belong[maxn];bool inq[maxn];void insert(int a,int b){    e[++cnt].to=b;e[cnt].next=head[a];head[a]=cnt;}void tarjan(int u){    dfn[u]=low[u]=++dfs_clock;    inq[u]=true;    stack[++scnt]=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(inq[v])low[u]=min(low[u],dfn[v]);    }    if(dfn[u]==low[u])    {        scccnt++;        int now=0;        while(now!=u)        {            now=stack[scnt--];            inq[now]=false;            belong[now]=scccnt;        }    }}int main(){    scanf("%d",&T);    while(T--)    {        scccnt=dfs_clock=cnt=0;        memset(head,0,sizeof head);        memset(dfn,0,sizeof dfn);        memset(low,0,sizeof low);        scanf("%d%d",&n,&m);        for(int i=1;i<=m;i++)        {            int x,y;char c1,c2;            getchar();            scanf("%c%d %c%d",&c1,&x,&c2,&y);            x=(x<<1)+(c1=='h');            y=(y<<1)+(c2=='h');            insert(x^1,y);            insert(y^1,x);        }        for(int i=2;i<=n*2+1;i++)if(!dfn[i])            tarjan(i);        bool ok=true;        for(int i=1;i<=n;i++)            if(belong[i<<1]==belong[(i<<1)+1])            {                ok=false;                break;            }        puts(ok?"GOOD":"BAD");    }}
原创粉丝点击