poj 3678 Katu Puzzle 2-SAT 建图入门

Description

Katu Puzzle is presented as a directed graph G(VE) 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 ≤ X≤ 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.

Input

The first line contains two integers N (1 ≤ N ≤ 1000) and M,(0 ≤ M ≤ 1,000,000) indicating the number of vertices and edges.
The following M lines contain three integers (0 ≤ a < N), b(0 ≤ b < N), c and an operator op each, describing the edges.

Output

Output a line containing "YES" or "NO".

Sample Input

4 4
0 1 1 AND
1 2 1 OR
3 2 0 AND
3 0 0 XOR

Sample Output

YES

Hint

X0 = 1, X1 = 1, X2 = 0, X3 = 1.

  根据上面直接建图

  

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <vector>
  5 #include <string>
  6 #include <algorithm>
  7 #include <queue>
  8 #include <stack>
  9
 10 using namespace std;
 11 const int maxn = 1e5 + 10;
 12 const int  mod = 1e9 + 7 ;
 13 const int INF = 0x7ffffff;
 14 struct node {
 15     int v, next;
 16 } edge[maxn];
 17 int head[maxn], dfn[maxn], low[maxn];
 18 int s[maxn], belong[maxn], instack[maxn];
 19 int tot, cnt, top, flag, n, m;
 20 void init() {
 21     tot = cnt = top = flag = 0;
 22     memset(s, 0, sizeof(s));
 23     memset(head, -1, sizeof(head));
 24     memset(dfn, 0, sizeof(dfn));
 25     memset(instack, 0, sizeof(instack));
 26 }
 27 void add(int u, int v ) {
 28     edge[tot].v = v;
 29     edge[tot].next = head[u];
 30     head[u] = tot++;
 31 }
 32 void tarjan(int v) {
 33     dfn[v] = low[v] = ++flag;
 34     instack[v] = 1;
 35     s[top++] = v;
 36     for (int i = head[v] ; ~i ; i = edge[i].next ) {
 37         int j = edge[i].v;
 38         if (!dfn[j]) {
 39             tarjan(j);
 40             low[v] = min(low[v], low[j]);
 41         } else if (instack[j]) low[v] = min(low[v], dfn[j]);
 42     }
 43     if (dfn[v] == low[v]) {
 44         cnt++;
 45         int t;
 46         do {
 47             t = s[--top];
 48             instack[t] = 0;
 49             belong[t] = cnt;
 50         } while(t != v) ;
 51     }
 52 }
 53 int check() {
 54     for (int i = 0 ; i < n ; i++)
 55         if (belong[2 * i] == belong[2 * i + 1]) return 0;
 56     return 1;
 57 }
 58 int main() {
 59     while(scanf("%d%d", &n, &m) != EOF) {
 60         if (n == 0 && m == 0) break;
 61         init();
 62         char op[10];
 63         int x, y, c;
 64         for (int i = 0 ; i < m ; i++) {
 65             scanf("%d%d%d%s", &x, &y, &c, op);
 66             if (op[0] == ‘A‘) {
 67                 if (c) {
 68                     add(2 * x + 1, 2 * x);
 69                     add(2 * y + 1, 2 * y);
 70                 } else {
 71                     add(2 * x, 2 * y + 1);
 72                     add(2 * y, 2 * x + 1);
 73                 }
 74             }
 75             if (op[0] == ‘O‘) {
 76                 if (c) {
 77                     add(2 * x + 1, 2 * y);
 78                     add(2 * y + 1, 2 * x);
 79                 } else {
 80                     add(2 * x, 2 * x + 1);
 81                     add(2 * y, 2 * y + 1);
 82                 }
 83             }
 84             if (op[0] == ‘X‘) {
 85                 if (c) {
 86                     add(2 * x, 2 * y + 1);
 87                     add(2 * x + 1, 2 * y);
 88                     add(2 * y, 2 * x + 1);
 89                     add(2 * y + 1, 2 * x);
 90                 } else {
 91                     add(2 * x + 1, 2 * y + 1);
 92                     add(2 * x, 2 * y);
 93                     add(2 * y + 1, 2 * x + 1);
 94                     add(2 * y, 2 * x);
 95                 }
 96             }
 97
 98         }
 99         for (int i = 0 ; i < 2 * n ; i++)
100             if (!dfn[i]) tarjan(i);
101         if (check()) printf("YES\n");
102         else printf("NO\n");
103     }
104     return 0;
105 }

原文地址:https://www.cnblogs.com/qldabiaoge/p/9094609.html

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

poj 3678 Katu Puzzle 2-SAT 建图入门的相关文章

[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 模板题)

题目链接: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)

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(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 ver

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(强连通 法)

题目链接 题意:给出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 不全为

POJ 3678 Katu Puzzle

2-SAT简单题.位运算写的时候忘记加括号WA了一发.... #include<cstdio> #include<cstring> #include<cmath> #include<queue> #include<vector> #include<stack> #include<algorithm> using namespace std; const int maxn=2000+10; int N,M; char s[1

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 2312Battle City(BFS-priority_queue 或者是建图spfa)

1 /* 2 bfs搜索!要注意的是点与点的权值是不一样的哦! 3 空地到空地的步数是1, 空地到墙的步数是2(轰一炮+移过去) 4 所以用到优先队列进行对当前节点步数的更新! 5 */ 6 #include<iostream> 7 #include<queue> 8 #include<cstring> 9 #include<algorithm> 10 #include<cstdio> 11 using namespace std; 12 13