[2-sat]模型基础(poj3678)

来源:互联网 发布:php运费模板源码 编辑:程序博客网 时间:2024/06/13 04:04

2-sat入门

sat问题是计算机科学的历史上一个非常著名的NPC问题。指的是,任何一个逻辑表达式都可以化简成为一个析取范式,而证明这个逻辑表达式是否可解。

解题的方法

这是一个图论的问题,而一般使用这样的解题方法;
对于一个逻辑变量p,如果p,p都必须要选择才可以解决这个逻辑表达式,那么很显然,这个逻辑表达式是不可解的。所以,我们就可以得到相应的解法了。
对于一个合取式(p+q),我们知道,如果p=0,则q=1,q=0,p=1,所以我们将一个逻辑变量看作两个点,一个是其本身,另一个是其反变量,如果p可以推出q,则在两个点之间连接一条边。
然后,使用tarjan算法,判断相同逻辑变量所代表的两个点是否在同一个强连通分量当中,最后得到相关的解。

一个例题

poj3678裸的2-sat模型,代码附上

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<vector>#include<stack>using namespace std;#define MAXN 2005struct Edge{    int to;    int next;}EdgeTable[MAXN*MAXN];int dfn[MAXN],low[MAXN];int head[MAXN];int state[MAXN],match[MAXN];int n,m,e,cnt,curT;stack<int>S;void addEdge(int from,int to){    EdgeTable[e].to=to;    EdgeTable[e].next=head[from];    head[from]=e++;}void Init(){    cnt=e=0;    memset(dfn,-1,sizeof(dfn));    memset(low,-1,sizeof(low));    memset(state,0,sizeof(state));    memset(head,-1,sizeof(head));}void processAND(int a,int b,int c){    if(c==1){        addEdge(a*2,b*2);        addEdge(a*2,b*2+1);        addEdge(a*2+1,b*2+1);        addEdge(b*2,a*2);        addEdge(b*2,a*2+1);        addEdge(b*2+1,a*2+1);    }    else{        addEdge(a*2+1,b*2);        addEdge(b*2+1,a*2);    }}void processOR(int a,int b,int c){    if(c==1){        addEdge(a*2,b*2+1);        addEdge(b*2,a*2+1);    }    else{        addEdge(a*2,b*2);        addEdge(b*2+1,a*2);        addEdge(a*2+1,b*2+1);        addEdge(b*2,a*2);        addEdge(a*2+1,b*2);        addEdge(b*2+1,a*2+1);    }}void processXOR(int a,int b,int c){    if(c==0){        addEdge(a*2,b*2);        addEdge(a*2+1,b*2+1);        addEdge(b*2,a*2);        addEdge(b*2+1,a*2+1);    }    else{        addEdge(a*2,b*2+1);        addEdge(a*2+1,b*2);        addEdge(b*2,a*2+1);        addEdge(b*2+1,a*2);    }}void get_Graph(){    int i,a,b,c;    char str[5];    for(i=0;i<m;i++){        scanf("%d%d%d%s",&a,&b,&c,str);        if(str[0]=='A')            processAND(a,b,c);        else if(str[0]=='O')            processOR(a,b,c);        else processXOR(a,b,c);    }    return;}void Dfs(int cur){    dfn[cur]=low[cur]=curT++;    state[cur]=1;    S.push(cur);    int i;    for(i=head[cur];i!=-1;i=EdgeTable[i].next){        int dest = EdgeTable[i].to;        if(state[dest]==1)            low[cur] = min(low[cur],low[dest]);        else if(!state[dest]){            Dfs(dest);            low[cur] = min(low[cur],low[dest]);        }    }    if(dfn[cur] == low[cur]){        while(!S.empty()){            int d = S.top();            S.pop();            state[d]=2;            match[d]=cnt;            if(d==cur)break;        }        cnt++;    }}void Solve(){    int i;    bool flag=true;    for(i=0;i<2*n;i++){        if(!state[i]){            curT=0;            Dfs(i);        }    }    for(i=0;i<n;i++){        if(match[i*2]==match[2*i+1]){            flag=false;            break;        }    }    if(flag)printf("YES\n");    else printf("NO\n");}int main(){    //freopen("input","r",stdin);    Init();    scanf("%d %d",&n,&m);    get_Graph();    Solve();}
0 0
原创粉丝点击