POJ 3678 Katu Puzzle(2

WBOY
リリース: 2016-06-07 15:48:30
オリジナル
1239 人が閲覧しました

POJ 3678 Katu Puzzle(2-SAT) http://poj.org/problem?id=3678 题意: 一个N个顶点和M条边的有向图,每个顶点能取0或1两个.现在每条边被一个操作符(or,and,xor)以及一个(0或1)标记了,表示a与b按操作符运算的结果是(0或1).问你该有向图是否有可行解? 分析: 由于

POJ 3678 Katu Puzzle(2-SAT)

http://poj.org/problem?id=3678

题意:

        一个N个顶点和M条边的有向图,每个顶点能取0或1两个值.现在每条边被一个操作符(or,and,xor)以及一个值(0或1)标记了,表示a与b按操作符运算的结果是值(0或1).问你该有向图是否有可行解?

分析:

        由于每个点只能取0或1两个值,所以我们把该问题转化为2-SAT问题.原图中的每个点对应2-SAT中的每个点.对于每种运算有下列转换方式:

a and b = 0 转换为 a=0 或 b=0

a and b = 1 转换为 a=1 且 b=1 即添加边 2*a->2*a+1  2*b->2*b+1(只要a0b0必然引起矛盾)

a or b = 0 转换为 2*a+1->2*2*b+1->2*b(只要a1b1必然引起矛盾)

a or b = 1 转换为 a=1 或b=1

a xorb=0转换为 a=1且b=1 或 a=0且b=0 即连下面的边:

2*a->2*b    2*b->2*a    2*a+1->2*b+1        2*b+1->2*a+1.

a xor b=1 转换为a=1且b=0 或a=0且b=1 则连下面的边:

2*a+1->2*b      2*b->2*a+1      2*a->2*b+1     2*b+1->2*a

AC代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn=1000+10;
struct TwoSAT
{
    int n;
    vector<int> G[maxn*2];
    int S[maxn*2],c;
    bool mark[maxn*2];

    bool dfs(int x)
    {
        if(mark[x^1]) return false;
        if(mark[x]) return true;
        mark[x]=true;
        S[c++]=x;
        for(int i=0;i<g if return false true void init n this->n=n;
        for(int i=0;i<n g memset void add_clause x xval y yval bool solve for i="0;i<2*n;i+=2)" if c="0;" while>0) mark[S[--c]]=false;
                if(!dfs(i+1)) return false;
            }
        }
        return true;
    }
}TS;
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    TS.init(n);
    int a,b,c;
    char op[10];
    for(int i=0;i<m scanf if ts.add_clause else printf return><br>


</m></n></g></int></vector></algorithm></cstring></cstdio>
ログイン後にコピー
関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート