poj3678Katu Puzzle(2sat入門)

這道題算是2sat建圖入門題。
把6種邏輯表達式轉化爲有向圖
2-sat就是合取範式
1.a&&b=1就相當於是a和b兩個析取式的合取範式,而a又可以寫成a||a。
2.a&&b=0 ==》 !a||!b=1
3 a||b=1
4 a||b=0 ==》 !a&&!b=1 同1
5 a^b=1 ==》(!a&&b)||(a&&!b)=1數理邏輯的知識可以推出
(a||b)&&(!a||!b)
6 a^b=0 ==》(!a&&b)||(a&&!b)=0 ==》 (a||!b)&&(!a||b)=1

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <stdlib.h>
#include <stack>
#include <vector>
#include <string.h>
#include <queue>
#define msc(X) memset(X,-1,sizeof(X))
#define ms(X) memset(X,0,sizeof(X))
typedef long long LL;
using namespace std;
const int MAXN=2005;
const int MAXM=4e6+5;
struct _Edge
{
    int to,next;
}edge[MAXM];
int tot,hd[MAXN];
void inti(void)
{
    tot=0;
    msc(hd);
}
void addedge(int u,int v)
{
    edge[tot].to=v;
    edge[tot].next=hd[u];
    hd[u]=tot++;
}
int Low[MAXN],DFN[MAXN],Stack[MAXN],Belong[MAXN];
int Index,top;
int scc;
bool Instack[MAXN];
void Tarjan(int u)
{
    int v;
    Low[u]=DFN[u]=++Index;
    Stack[top++]=u;
    Instack[u]=true;
    for(int i=hd[u];i!=-1;i=edge[i].next)
    {
        v=edge[i].to;
        if(!DFN[v]){
            Tarjan(v);
            if(Low[u]>Low[v]) Low[u]=Low[v];
        }
        else if(Instack[v]&&Low[u]>DFN[v])
            Low[u]=DFN[v];
    }
    if(Low[u]==DFN[u]){
        scc++;
        do{
            v=Stack[--top];
            Instack[v]=false;
            Belong[v]=scc;
        }while(v!=u);
    }
}
int main(int argc, char const *argv[])
{
    int n,m;
    while(scanf("%d %d",&n,&m)==2){
        inti();
        while(m--){
            char s[5];
            int a,b,c;
            scanf("%d %d %d %s",&a,&b,&c,s);
            if(s[0]=='A'){
                if(c==1){// a&&b=1分解爲a||a和b||b
                    addedge(a<<1,a<<1|1);//a<<1表示!a
                    addedge(b<<1,b<<1|1);
                }
                else{//a&&b=0即!a||!b
                    addedge(a<<1|1,b<<1);
                    addedge(b<<1|1,a<<1);
                }
            }
            else if(s[0]=='O'){
                if(c==1){//a||b=1
                    addedge(a<<1,b<<1|1);
                    addedge(b<<1,a<<1|1);
                }
                else{//a||b=0即!a&&!b=1
                    addedge(a<<1|1,a<<1);
                    addedge(b<<1|1,b<<1);
                }
            }
            else{
                if(c==1){//a^b=1分解(a||b)和(!a||!b)
                    addedge(a<<1,b<<1|1);
                    addedge(b<<1,a<<1|1);
                    addedge(a<<1|1,b<<1);
                    addedge(b<<1|1,a<<1);
                }
                else{//a^b=0即(a||!b)和(!a||b)
                    addedge(a<<1,b<<1);
                    addedge(b<<1|1,a<<1|1);
                    addedge(a<<1|1,b<<1|1);
                    addedge(b<<1,a<<1);
                }
            }
        }

        //強連通分量判斷
        ms(DFN);
        ms(Instack);
        Index=scc=top=0;
        for(int i=0;i<2*n;i++)
            if(!DFN[i]) Tarjan(i);
        bool flg=false;
        for(int i=0;i<n;i++)
            if(Belong[i<<1]==Belong[i<<1|1])
            {
                flg=true;break;
            }
        puts(flg?"NO":"YES");
    }
    return 0;
}
發佈了110 篇原創文章 · 獲贊 3 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章