zoukankan      html  css  js  c++  java
  • poj3678 Katu Puzzle

    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
  • 相关阅读:
    HashMap底层实现原理/HashMap与HashTable区别/HashMap与HashSet区别(转)
    JSP语法
    Web开发基础(读书笔记)
    eclispe新导入的文件有个小红叉号(x)的问题
    Vue处理数据,数组更新,但视图无法得到及时更新
    VUE 利用tab切换+同路由跳转传参(check)+vant上拉加载制作订单列表(终)
    适配方案一之:利用rem和less计算制作移动端适配页面
    Git常用命令务忘
    git提交代码步骤笔记
    Vue仿淘宝订单状态的tab切换效果——(但现实中不会用此种方式进行存储数据)
  • 原文地址:https://www.cnblogs.com/Rorshach/p/8684599.html
Copyright © 2011-2022 走看看