码迷,mamicode.com
首页 > 其他好文 > 详细

poj3678 Katu Puzzle

时间:2018-03-31 23:58:38      阅读:346      评论:0      收藏:0      [点我收藏+]

标签:i++   opened   code   push   name   iostream   ace   script   esc   

Description:

  有N个变量,每个变量取值可能是0或1,给定M个算式,表示a与b进行op运算结果为c,op为与、或、亦或的一种,求是否存在对每个变量的合法赋值

 

思路:

  分三种情况讨论,建立2-sat模型,1 ~n表示该值取值为0,n+1 ~ 2n表示该值取值为1

1.    a and b = 0。这表示如果a为1,b就必须为0,所以把(a+n,b)连有向边。同理,并将(b+n, a)连有向边

       a and b = 1。这表示a和b必须为1,所以a为0,a就必须为1,然后将(a,a+n)连有向边,同理,将(b,b+n)连有向边

2.   a or b = 1或者0。方法和上面差不多

3.   a xor b  = 1,这表示a如果为1,b必须为0,a如果为0,b必须为1。所以将(a+n,b)和(a,b+n)连有向边,同样的,连边(b,a+n),(b+n,a);

      a xor b = 0,同上分析即可

技术分享图片
#include<iostream>
#include<cstring>
#include<cstdio>
#include<stack>
using namespace std;
const int N = 2010, M = 1e6 + 100;

int head[N], now;
struct edges{
    int to, next, w;
}edge[M<<1];
void add(int u, int v){ edge[++now] = {v, head[u]}; head[u] = now;}

int n, m, dfn[N], cnt, low[N], dict[N], tot;
bool ins[N];
stack<int> sta;
void tarjan(int x){
    dfn[x] = low[x] = ++cnt;
    sta.push(x); ins[x] = 1;
    for(int i = head[x]; i; i = edge[i].next){
        int v = edge[i].to;
        if(!dfn[v]){
            tarjan(v);
            low[x] = min(low[x], low[v]);
        }
        else if(ins[v]) low[x] = min(low[x], dfn[v]);
    }
    if(dfn[x] == low[x]){
        tot++; int tmp = -1;
        do{
            tmp = sta.top(); sta.pop();
            ins[tmp] = 0; 
            dict[tmp] = tot;
        }while(tmp != x);
    }
    return ;
}
int main(){
    scanf("%d%d", &n, &m);
    int x, y, c;
    char str[20];
    bool flag = 0;
    for(int i = 1; i <= m; i++){
        scanf("%d%d%d%s", &x, &y, &c, str);
        x++, y++;
        if(str[0] == A){
            if(!c) add(y + n, x), add(x + n, y);
            if(c) add(x, x + n), add(y, y + n);
        }
        if(str[0] == O){
            if(!c) add(x + n, x), add(y + n, y);
            if(c) add(y, x + n), add(x, y + n);
        }
        if(str[0] == X){
            if(!c) add(x, y), add(y, x), add(x + n, y + n), add(y + n, x + n);
            if(c) add(x, y + n), add(y, x + n), add(x + n, y), add(y + n, x);
        }
    }
    for(int i = 1; i <= 2 * n; i++)
      if(!dfn[i]) tarjan(i);
    for(int i = 1; i <= n; i++)
      if(dict[i] == dict[i + n]){
        puts("NO"); return 0;
      }
    puts("YES");
    return 0;
}
View Code

 

poj3678 Katu Puzzle

标签:i++   opened   code   push   name   iostream   ace   script   esc   

原文地址:https://www.cnblogs.com/Rorshach/p/8684599.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!