2-SAT问题

Posted 钟钟终

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2-SAT问题相关的知识,希望对你有一定的参考价值。

P4782 【模板】2-SAT 问题

在拓扑序上的表现为:我们要在两种取值中选择拓扑序较大的那个值;
越靠近叶节点的那些节点在 TarjanTarjan 的时候是越早被缩点的,所以拓扑序越大的点其所在强联通分量编号越小
强联通分量编号越小 -> 拓扑序越大 -> 越优

#include <bits/stdc++.h>

using namespace std;
const int maxn=1e7+5;
int n,m,head[maxn],nxt[maxn],vi[maxn],cnt,tim;
int dfn[maxn],low[maxn],inq[maxn],tol,ans,belong[maxn];
void add(int from,int to)

    vi[++cnt]=to;
    nxt[cnt]=head[from];
    head[from]=cnt;

stack<int>q;
void tarjan(int u)

    dfn[u]=low[u]=++tim;
    q.push(u);
    inq[u]=1;
    for(int i=head[u];i;i=nxt[i])
    
        int v=vi[i];
        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])
    
        tol++;int tmp;
        do
        
            tmp=q.top();q.pop();
            inq[tmp]=0;
            belong[tmp]=tol;
        while(tmp!=u);
    

int main()

    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    
        int a,x,b,y;scanf("%d%d%d%d",&a,&x,&b,&y);
        if(x==0&&y==0)
        
            add(a+n,b);
            add(b+n,a);
        
        if(x==0&&y==1) //a=0 or b=1
        
            add(a+n,b+n);
            add(b,a);
        
        if(x==1&&y==0)
        
            add(a,b);
            add(b+n,a+n);
        
        if(x==1&&y==1)
        
            add(a,b+n);
            add(b,a+n);
        
    
    for(int i=1;i<=2*n;i++)
    
        if(!dfn[i])
            tarjan(i);
    
    for(int i=1;i<=n;i++)
    
        if(belong[i]==belong[i+n])
        
            cout<<"IMPOSSIBLE"<<endl;;
            return 0;
        
    
    cout<<"POSSIBLE"<<endl;
    for(int i=1;i<=n;i++)
    
        if(belong[i]>belong[i+n])
            cout<<"1 ";
        else
            cout<<"0 ";
    
    cout<<endl;
    return 0;

P4171 [JSOI2010] 满汉全席

#include <bits/stdc++.h>

using namespace std;
const int maxn=400;
int t,n,m;
struct node

    int v,nxt;
E[4010];
int head[maxn],tot;
int low[maxn],dfn[maxn],cnt;
int col[maxn],ins[maxn],colnum;
stack<int> st;
char s1[5],s2[5];

void add(int u,int v)

    E[++tot].nxt=head[u];
    E[tot].v=v;
    head[u]=tot;


void tarjan(int u)

    low[u]=dfn[u]=++cnt;
    st.push(u); ins[u]=1;
    for(int i=head[u];i;i=E[i].nxt)
    
        int v=E[i].v;
        if(!dfn[v]) tarjan(v); low[u]=min(low[u],low[v]);
        else if(ins[v])
        low[u]=min(low[u],dfn[v]);
    
    if(low[u]==dfn[u])
    
        int v; colnum++;
        do
            v=st.top();
            st.pop(); ins[v]=0;
            col[v]=colnum;
        
        while(v!=u);
    


void init()

    tot=cnt=colnum=0;
    memset(head,0,sizeof(head));
    memset(col,0,sizeof(col));
    memset(low,0,sizeof(low));
    memset(dfn,0,sizeof(dfn));


int main()

    cin>>t;
    while(t--)
    
        init();
        cin>>n>>m;
        for(int i=1;i<=m;++i)//h-1,m-0
        
            string s1,s2;cin>>s1>>s2;
            int a=0,b=0,k;
            k=1; while(s1[k]>='0'&&s1[k]<='9')a=a*10+s1[k++]-'0';
            k=1; while(s2[k]>='0'&&s2[k]<='9')b=b*10+s2[k++]-'0';
            if(s1[0]=='m'&&s2[0]=='m')
            
                add(a+n,b);
                add(b+n,a);
            
            else if(s1[0]=='m'&&s2[0]=='h') //a=0 or b=1
            
                add(a+n,b+n);
                add(b,a);
            
            else if(s1[0]=='h'&&s2[0]=='m')
            
                add(a,b);
                add(b+n,a+n);
            
            else if(s1[0]=='h'&&s2[0]=='h')
            
                add(a,b+n);
                add(b,a+n);
            
        

        for(int i=1;i<=n<<1;++i)
        if(!dfn[i])tarjan(i);
        int judge=0;
        for(int i=1;i<=n;++i)
        if(col[i]==col[i+n])
        
            judge=1;break;
        

        if(judge)
            printf("BAD\\n");
        else
            printf("GOOD\\n");
    
    return 0;

以上是关于2-SAT问题的主要内容,如果未能解决你的问题,请参考以下文章

2-SAT 问题与解法小结

2-SAT

(转)2-SAT小结

[模板]2-SAT 问题

(转)2-sat小结

2-CNF SAT如何在P中,而3-CNF SAT在NPC中?