POJ - 3678 - Katu Puzzle(2SAT)

链接:

https://vjudge.net/problem/POJ-3678

题意:

Katu Puzzle is presented as a directed graph G(V, E) 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 ≤ Xi ≤ 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.

思路:

枚举每用到的两个点,当不满足的时候加另外两种情况进图。
找出不能同时存在的情况,表示另外的情况必须存在。

代码:

//#include<bits/stdc++.h>
#include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<string.h>
#include<cstring>
#include<set>
#include<queue>
#include<algorithm>
#include<math.h>
#include<stdio.h>
#include<map>
#include<stack>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int MOD = 20071027;
const int MAXN = 1e3+10;
int Next[4][2] = {-1, 0, 0, 1, 1, 0, 0, -1};

int Map[MAXN][MAXN];
int Val[MAXN][MAXN];
vector<int> G[MAXN*2], Gt[MAXN*2];
int sccnum[MAXN*2], dfn[MAXN*2], low[MAXN*2];
int opp[MAXN*2], disin[MAXN*2], col[MAXN*2];
stack<int> St;
int n, m, scc_cnt, dfn_clock;

void tarjan(int u)
{
    dfn[u] = low[u] = ++dfn_clock;
    St.push(u);
    for (int i = 0;i < (int)G[u].size();i++)
    {
        int v = G[u][i];
        if (!dfn[v])
        {
            tarjan(v);
            low[u] = min(low[u], low[v]);
        }
        else if (!sccnum[v])
            low[u] = min(low[u], dfn[v]);
    }

    if (low[u] == dfn[u])
    {
        ++scc_cnt;
        while(true)
        {
            int x = St.top();
            St.pop();
            sccnum[x] = scc_cnt;
            if (x == u)
                break;
        }
    }
}

bool solve()
{
    memset(dfn, 0, sizeof(dfn));
    memset(low, 0, sizeof(low));
    memset(sccnum, 0, sizeof(sccnum));
    dfn_clock = scc_cnt = 0;
    for (int i = 0;i < 2*n;i++)
        if (!dfn[i]) tarjan(i);
    for (int i = 0;i < 2*n;i+=2)
    {
        if (sccnum[i] == sccnum[i+1])
            return false;
    }
    return true;
}

bool check(int l1, int r1, int l2, int r2)
{
    if (r1 <= l2 || r2 <= l1)
        return false;
    return true;
}

void tupo()
{
    memset(disin, 0, sizeof(disin));
    memset(col, -1, sizeof(col));
    for (int i = 0;i < 2*n;i++) Gt[i].clear();
    for (int i = 0;i < 2*n;i++)
    {
        for (int j = 0;j < (int)G[i].size();j++)
        {
            int to = G[i][j];
            if (sccnum[i] == sccnum[to]) continue;
            Gt[sccnum[to]].push_back(sccnum[i]);
            disin[sccnum[i]]++;
        }
    }
    queue<int> que;
    for (int i = 1;i <= scc_cnt;i++)
        if (!disin[i]) que.push(i);
    while(!que.empty())
    {
        int u = que.front();
        que.pop();
        if (col[u] == -1)
        {
            col[u] = 1;
            col[opp[u]] = 0;
        }
        for (int i = 0;i < (int)Gt[u].size();i++)
        {
            int to = Gt[u][i];
            if (--disin[to] == 0)
                que.push(to);
        }
    }
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    while(cin >> n >> m)
    {
        memset(Map, 0, sizeof(Map));
        memset(Val, 0, sizeof(Val));
        for (int i = 0;i < 2*n;i++)
            G[i].clear();
        int a, b, c;
        char op[10];
        for (int i = 1;i <= m;i++)
        {
            cin >> a >> b >> c >> op;
            for (int va = 0;va <= 1;va++)
            {
                for (int vb = 0;vb <= 1;vb++)
                {
                    int tmp;
                    if (op[0] == 'A')
                        tmp = va&vb;
                    if (op[0] == 'O')
                        tmp = va|vb;
                    if (op[0] == 'X')
                        tmp = va^vb;
                    if (tmp != c)
                    {
                        G[a*2+va].push_back((b*2+vb)^1);
                        G[b*2+vb].push_back((a*2+va)^1);
                    }
                }
            }
        }
        if (solve())
            cout << "YES\n" ;
        else
            cout << "NO\n" ;
    }

    return 0;
}

原文地址:https://www.cnblogs.com/YDDDD/p/12153375.html

时间: 2024-08-08 11:24:32

POJ - 3678 - Katu Puzzle(2SAT)的相关文章

POJ 3678 Katu Puzzle(2-sat 模板题)

题目链接:http://poj.org/problem?id=3678 Description Katu Puzzle is presented as a directed graph G(V, E) 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

POJ 3678 Katu Puzzle (2-SAT,常规)

题意:给出n个点,每个点上有一个数字可以0或1,然后给出m条限制,要求a和b两个点上的数字满足 a op b = c,op和c都是给定.问是否能够有一组解满足所有限制?(即点上的数字是0是1由你决定) 思路:题意很清晰了,难点在建图.要考虑所有可能的冲突: 当op为and: (1)c为0时,其中1个必为0. (2)c为1时,两者必为1.要加两条边,形如 a0->a1. 当op为or: (1)c为0时,两者必为0.要加两条边,形如 a1->a0. (2)c为1时,其中1个必为1. 当op为xor

POJ 3678 Katu Puzzle (2-sat基础)

题意:每个数只有0,1两种可能,给出两两之间的AND,OR,XOR的值,判断有没有解 裸题. #include<cstdio> #include<iostream> #include<cstring> #include<algorithm> using namespace std; const int N = 2010; struct Edge { int v,next; }es[N*N]; int head[N]; int n,m; int tmp[N],

POJ 3678 Katu Puzzle(强连通 法)

题目链接 题意:给出a, b, c 和操作类型 (与或异或),问是否满足所有的式子 主要是建图: 对于 and , c == 1: 说明 a 和 b都是1,那么 0 就不能取, a' -> a , b' - > b ,因为 a 和 a'是对立事件,对于 a' - >a说明,a'如果成立,那么a也一定存在,显然这是不可能的所以a'不会 成立的. c == 0 说明 a 和 b不全为1, a' -> b , b' -> a 对于 or,  c == 1 :说明 a 和 b 不全为

[2-SAT] poj 3678 Katu Puzzle

题目链接: http://poj.org/problem?id=3678 Katu Puzzle Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7888   Accepted: 2888 Description Katu Puzzle is presented as a directed graph G(V, E) with each edge e(a, b) labeled by a boolean operator 

poj 3678 Katu Puzzle(2-sat)

Description Katu Puzzle is presented as a directed graph G(V, E) 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 ≤ Xi ≤ 1) s

poj 3678 Katu Puzzle 2-SAT 建图入门

Description Katu Puzzle is presented as a directed graph G(V, E) 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 ≤ Xi ≤ 1) s

POJ 3678--Katu Puzzle(2-SAT)

感觉这题比较裸,表现出了2-sat的本质. 不过构图我想的还是太简单了,a&b=1我只连了 a1->b1,b1->a1,但其实是不对的.这样连,a0和b0可以同时选到.应该连a0->a1,b0->b1这样就能保证a0,b0都不被选到.或运算同理. #include <algorithm>#include <iostream>#include <cstring>#include <string>#include <vect

poj 2749 Building roads(2-sat)

Description Farmer John's farm has N barns, and there are some cows that live in each barn. The cows like to drop around, so John wants to build some roads to connect these barns. If he builds roads for every pair of different barns, then he must bui