题目链接 poj 3678
Katu Puzzle
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 8340 | Accepted: 3077 |
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) 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:
|
|
|
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 a (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.
这是我的第一道2-sat题,参考璇神思路和代码,终于ac了。
将一个点拆分成X(2*i)与非X(2*i+1)两点,然后按照与,或,异或的运算规则,推出每一组运算对象的充分条件并建边。跑一遍强连通,判断每一组x与非x是否在同一个强连通分量中,如果是,则输出no,否则输出yes。理由是:如果一个点可以取两种状态(0,1),这显然(请原谅我用这个不礼貌的词)不合题意
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <map> #include <stack> #include <sstream> #include <cmath> #include <queue> #include <string> #include <vector> //#pragma comment(linker, "/STACK:1024000000,1024000000") //#include<bits/stdc++.h> #define zeros(a) memset(a,0,sizeof(a)) #define ones(a) memset(a,-1,sizeof(a)) #define lson step<<1 #define rson lson+1 #define esp 1e-6 #define oo 0x3fffffff #define TEST cout<<"*************************"<<endl; using namespace std; typedef long long ll; const int maxn=2000+10; const int maxm=1000000+10; struct side { int v,next; }e[maxm<<2]; int dfn[maxn],head[maxn],low[maxn],belong[maxn],s[maxn],in_s[maxn]; int T,tot,top,index; int n,m; char str[5]; inline int Min(int a,int b) { return a<b?a:b; } void build(int u,int v) { e[T].v=v; e[T].next=head[u]; head[u]=T++; } void init() { ones(head); zeros(belong); zeros(low); ones(dfn); zeros(s); zeros(in_s); index=top=T=0; tot=1; } void tarjan(int u) { dfn[u]=low[u]=tot++; in_s[u]=1; s[++top]=u; for(int i=head[u];~i;i=e[i].next) { int v=e[i].v; if(dfn[v]==-1) { tarjan(v); low[u]=Min(low[v],low[u]); } else if(in_s[v]) low[u]=Min(low[u],dfn[v]); } if(low[u]==dfn[u]) { index++; int temp; do { temp=s[top--]; in_s[temp]=0; belong[temp]=index; }while(temp!=u); } } int main() { //freopen("in.txt","r",stdin); int T_T; //scanf("%d",T_T); while(~scanf("%d%d",&n,&m)) { init(); int a,b,c; for(int i=0;i<m;i++) { scanf("%d%d%d%s",&a,&b,&c,str); if(str[0]==‘A‘) { if(c==1) { build(2*a,2*a+1); build(2*b,2*b+1); } else { build(2*a+1,2*b); build(2*b+1,2*a); } } else if(str[0]==‘O‘) { if(c==0) { build(2*a+1,2*a); build(2*b+1,2*b); } else { build(2*a,2*b+1); build(2*b,2*a+1); } } else { if(c==1) { build(2*a+1,2*b); build(2*b,2*a+1); build(2*b+1,2*a); build(2*a,2*b+1); } else { build(2*a,2*b); build(2*b,2*a); build(2*a+1,2*b+1); build(2*b+1,2*a+1); } } } for(int i=0;i<2*n;i++) { if(dfn[i]==-1) { tarjan(i); } } int flag=1; for(int i=0;i<n;i++) { if(belong[2*i]==belong[2*i+1]) { flag=0; break; } } if(flag) printf("YES\n"); else printf("NO\n"); } return 0; }