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;
}

猜你喜欢

转载自www.cnblogs.com/YDDDD/p/12153375.html
今日推荐