zoukankan      html  css  js  c++  java
  • poj 3678 2-sat(强连通)

    题目链接 poj 3678
    Katu Puzzle
    Time Limit: 1000MS   Memory Limit: 65536K
    Total Submissions: 8340   Accepted: 3077

    Description

    Katu Puzzle is presented as a directed graph G(VE) with each edge e(a, b) labeled by a boolean operator op (one of AND, OR, XOR) and an integer c (0 ≤ c ≤ 1). One Katu is solvable if one can find each vertex Vi a value Xi (0 ≤ X≤ 1) such that for each edge e(a, b) labeled by op and c, the following formula holds:

     Xa op Xb = c

    The calculating rules are:

    AND 0 1
    0 0 0
    1 0 1
    OR 0 1
    0 0 1
    1 1 1
    XOR 0 1
    0 0 1
    1 1 0

    Given a Katu Puzzle, your task is to determine whether it is solvable.

    Input

    The first line contains two integers N (1 ≤ N ≤ 1000) and M,(0 ≤ M ≤ 1,000,000) indicating the number of vertices and edges.
    The following M lines contain three integers (0 ≤ a < N), b(0 ≤ b < N), c and an operator op each, describing the edges.

    Output

    Output a line containing "YES" or "NO".

    Sample Input

    4 4
    0 1 1 AND
    1 2 1 OR
    3 2 0 AND
    3 0 0 XOR

    Sample Output

    YES

    Hint

    X0 = 1, X1 = 1, X2 = 0, X3 = 1.
    这是我的第一道2-sat题,参考璇神思路和代码,终于ac了。
    将一个点拆分成X(2*i)与非X(2*i+1)两点,然后按照与,或,异或的运算规则,推出每一组运算对象的充分条件并建边。跑一遍强连通,判断每一组x与非x是否在同一个强连通分量中,如果是,则输出no,否则输出yes。理由是:如果一个点可以取两种状态(0,1),这显然(请原谅我用这个不礼貌的词)不合题意
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <map>
    #include <stack>
    #include <sstream>
    #include <cmath>
    #include <queue>
    #include <string>
    #include <vector>
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    //#include<bits/stdc++.h>
    #define zeros(a) memset(a,0,sizeof(a))
    #define ones(a) memset(a,-1,sizeof(a))
    #define lson step<<1
    #define rson lson+1
    #define esp 1e-6
    #define oo 0x3fffffff
    #define TEST cout<<"*************************"<<endl;
    
    using namespace std;
    typedef long long ll;
    const int maxn=2000+10;
    const int maxm=1000000+10;
    struct side
    {
        int v,next;
    }e[maxm<<2];
    int dfn[maxn],head[maxn],low[maxn],belong[maxn],s[maxn],in_s[maxn];
    int T,tot,top,index;
    int n,m;
    char str[5];
    inline int Min(int a,int b)
    {
        return a<b?a:b;
    }
    void build(int u,int v)
    {
        e[T].v=v;
        e[T].next=head[u];
        head[u]=T++;
    }
    void init()
    {
        ones(head);
        zeros(belong);
        zeros(low);
        ones(dfn);
        zeros(s);
        zeros(in_s);
        index=top=T=0;
        tot=1;
    }
    void tarjan(int u)
    {
        dfn[u]=low[u]=tot++;
        in_s[u]=1;
        s[++top]=u;
        for(int i=head[u];~i;i=e[i].next)
        {
            int v=e[i].v;
            if(dfn[v]==-1)
            {
                tarjan(v);
                low[u]=Min(low[v],low[u]);
            }
            else if(in_s[v])
                low[u]=Min(low[u],dfn[v]);
        }
        if(low[u]==dfn[u])
        {
            index++;
            int temp;
            do
            {
                temp=s[top--];
                in_s[temp]=0;
                belong[temp]=index;
            }while(temp!=u);
         }
    }
    int main()
    {
        //freopen("in.txt","r",stdin);
        int T_T;
        //scanf("%d",T_T);
        while(~scanf("%d%d",&n,&m))
        {
            init();
            int a,b,c;
            for(int i=0;i<m;i++)
            {
                scanf("%d%d%d%s",&a,&b,&c,str);
                if(str[0]=='A')
                {
                    if(c==1)
                    {
                        build(2*a,2*a+1);
                        build(2*b,2*b+1);
                    }
                    else
                    {
                        build(2*a+1,2*b);
                        build(2*b+1,2*a);
                    }
                }
                else if(str[0]=='O')
                {
                    if(c==0)
                    {
                        build(2*a+1,2*a);
                        build(2*b+1,2*b);
                    }
                    else
                    {
                        build(2*a,2*b+1);
                        build(2*b,2*a+1);
                    }
                }
                else
                {
                    if(c==1)
                    {
                        build(2*a+1,2*b);
                        build(2*b,2*a+1);
                        build(2*b+1,2*a);
                        build(2*a,2*b+1);
                    }
                    else
                    {
                        build(2*a,2*b);
                        build(2*b,2*a);
                        build(2*a+1,2*b+1);
                        build(2*b+1,2*a+1);
                    }
                }
            }
            for(int i=0;i<2*n;i++)
            {
                if(dfn[i]==-1)
                {
                    tarjan(i);
                }
            }
            int flag=1;
            for(int i=0;i<n;i++)
            {
                if(belong[2*i]==belong[2*i+1])
                {
                    flag=0;
                    break;
                }
            }
            if(flag)
                printf("YES
    ");
            else
                printf("NO
    ");
        }
        return 0;
    }
    不为失败找借口,只为成功找方法
  • 相关阅读:
    4500 小Q系列故事——屌丝的逆袭
    HDU 1171 Big Event in HDU
    linux库文件 /usr/lib
    HDU 1860 统计字符
    编程之美~~传话游戏
    HDU 1087 Super Jumping! Jumping! Jumping!
    HDU 1203 I NEED A OFFER!
    各种树
    HDU 3127 WHUgirls
    01背包 完全背包 多重背包 二维费用背包
  • 原文地址:https://www.cnblogs.com/youmi/p/4533384.html
Copyright © 2011-2022 走看看