zoukankan      html  css  js  c++  java
  • poj 3678 2-SAT问题

    思路:将每个点拆分为两个点 a与a' ,a表示为1,a'表示为0。那么条件给的每个边自然就会存在矛盾,然后根据2-SAT建边就行了。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<vector>
    #define Maxn 3010
    #define Maxm 1000000
    using namespace std;
    int dfn[Maxn],low[Maxn],vi[Maxn],head[Maxn],e,n,m,lab,top,Stack[Maxn],num,id[Maxn];
    struct Edge{
        int u,v,next,l;
    }edge[Maxm];
    void init()
    {
        int i,j;
        memset(dfn,0,sizeof(dfn));
        memset(low,0,sizeof(low));
        memset(head,-1,sizeof(head));
        memset(id,0,sizeof(id));
        memset(vi,0,sizeof(vi));
        e=lab=num=top=0;
    }
    void add(int u,int v)
    {
        edge[e].u=u,edge[e].v=v,edge[e].next=head[u],head[u]=e++;
    }
    void Tarjan(int u)
    {
        int i,j,v;
        dfn[u]=low[u]=++lab;
        Stack[top++]=u;
        vi[u]=1;
        for(i=head[u];i!=-1;i=edge[i].next)
        {
            v=edge[i].v;
            if(!dfn[v])
            {
                Tarjan(v);
                low[u]=min(low[u],low[v]);
            }
            if(vi[v])
            low[u]=min(low[u],dfn[v]);
        }
        if(low[u]==dfn[u])
        {
            ++num;
            do{
                i=Stack[--top];
                vi[i]=0;
                id[i]=num;
            }while(i!=u);
        }
    }
    int solve()
    {
        int i,j;
        for(i=1;i<=n*2;i++)
        {
            if(!dfn[i])
                Tarjan(i);
        }
        for(i=1;i<=n;i++)
        {
                if(id[i]==id[i+n])
                return 0;
        }
        return 1;
    }
    int main()
    {
        int i,j,a,b,c;
        char str[10];
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            init();
            for(i=1;i<=m;i++)
            {
                scanf("%d%d%d%s",&a,&b,&c,&str);
                a++,b++;
                if(str[0]=='O')
                {
                    if(c==0)
                    {
                        add(a,b+n);
                        add(a,b);
                        add(b,a+n);
                        add(b,a);
                        add(a+n,b+n);
                        add(b+n,a+n);
                    }
                    else
                    {
                        add(a+n,b);
                        add(b+n,a);
                    }
                }
                if(str[0]=='A')
                {
                    if(c==0)
                    {
                        add(a,b+n);
                        add(b,a+n);
                    }
                    else
                    {
                        add(a+n,b);
                        add(a,b);
                        add(b+n,a);
                        add(b,a);
                        add(a+n,b+n);
                        add(b+n,a+n);
                    }
                }
                if(str[0]=='X')
                {
                    if(c==0)
                    {
                        add(a,b);
                        add(b+n,a+n);
                        add(b,a);
                        add(a+n,b+n);
                    }
                    else
                    {
                        add(a,b+n);
                        add(b,a+n);
                        add(a+n,b);
                        add(b+n,a);
                    }
                }
            }
            if(solve())
                printf("YES
    ");
            else
                printf("NO
    ");
        }
        return 0;
    }
  • 相关阅读:
    RSA算法
    随机数相关面试题
    黑冰
    Servlet
    中国文人的弱点
    黑客与画家
    J2SE、JS及JavaWeb的若干知识
    离婚前规则
    自己写的一个智能指针类
    用_makepath和_splitpath构造路径&分解路径
  • 原文地址:https://www.cnblogs.com/wangfang20/p/3219952.html
Copyright © 2011-2022 走看看