POJ3678 Katu Puzzle (2-SAT检验)

来源:互联网 发布:cc免费顶级域名注册 编辑:程序博客网 时间:2024/04/30 18:41

这题是2-SAT的经典题,鉴于n*m挺大的,所以就用强连通缩点的方式检验。

3种逻辑操作很简单,建边不难,注意对称性。

如果碰到 A && B==1 -> A=B=1
建立边是 从 ~A到A,从~B到B 连一条的。
其他的注意细节就好了。

#include<iostream>#include<string.h>#include<string>#include<algorithm>#include<stdio.h>#include<vector>#include<stack>using namespace std;//???????????vector<int> G[2200];bool vis[2200];int scc[2200];int dfs_clock=0;int scc_cnt=0;stack<int> stk;int DFN[2200];int low[2200];int n,m;char input[30];void init(){    dfs_clock=0;    scc_cnt=0;    for(int i=0;i<2200;i++)    {        G[i].clear();        vis[i]=0;        scc[i]=0;        DFN[i]=0;        low[i]=0;    }}int dfs(int now,int fa){    vis[now]=1;    DFN[now]=low[now]=++dfs_clock;    int size=G[now].size();    stk.push(now);    for(int i=0;i<size;i++)    {        int v=G[now][i];        if(vis[v]==0)        {            low[now]=min(low[now],dfs(v,now));        }        else if(scc[v]==0)        {            low[now]=min(low[now],DFN[v]);        }    }    if(DFN[now]==low[now])    {        scc_cnt++;        int x=-1;        do        {            x=stk.top();            stk.pop();            scc[x]=scc_cnt;        }while(x!=now);    }    return low[now];}int main(){    while(cin>>n>>m)    {        init();        for(int i=0;i<m;i++)        {            int a,b,c;            scanf("%d %d %d",&a,&b,&c);            scanf("%s",input);            a=2*a;            b=2*b;            if(strcmp(input,"AND")==0)            {                if(c==1)                {                    G[a^1].push_back(a);                    G[b^1].push_back(b);                }                else                {                    G[a].push_back(b^1);                    G[b].push_back(a^1);                }            }            if(strcmp(input,"OR")==0)            {                if(c==1)                {                    G[a^1].push_back(b);                    G[b^1].push_back(a);                }                else                {                    G[a].push_back(a^1);                    G[b].push_back(b^1);                }            }            if(strcmp(input,"XOR")==0)            {                if(c==1)                {                    G[a].push_back(b^1);                    G[b].push_back(a^1);                    G[a^1].push_back(b);                    G[b^1].push_back(a);                }                else                {                    G[a].push_back(b);                    G[b].push_back(a);                    G[a^1].push_back(b^1);                    G[b^1].push_back(a^1);                }            }        }        for(int i=0;i<2*n;i++)        {            if(vis[i]==0) dfs(i,-1);        }        bool judge=true;        for(int i=0;i<2*n;i+=2)        {            if(scc[i]==scc[i+1])            {                judge=false;                break;            }        }        if(judge==false)        {            printf("NO\n");        }        else printf("YES\n");    }    return 0;}
0 0
原创粉丝点击