题目链接:
http://poj.org/problem?id=3678
Katu Puzzle
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 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. Source |
[Submit] [Go Back] [Status]
[Discuss]
题目意思:
给一幅有向图,每条边代表连接的两个节点的一种运算,并且告诉运算后的值,问能否有一种节点取值,使得各边都满足边的运算。
解题思路:
2-SAT
i代表1 ~i带表0
当i&j==1时,建边 ~i->i ~j->j
当i&j==0时,建边 i->~j j->~i ~i->~j ~j->~i
当i|j==1时,建边 ~i->j ~j->i
当i|j==0时,建边 i->~i j->~j
当i^j==1时,建边 i->~j ~i->j j->~i ~j->i
当i^j==0时,建边 i->j ~i->~j j->i ~j->~i
代码:
//#include<CSpreadSheet.h> #include<iostream> #include<cmath> #include<cstdio> #include<sstream> #include<cstdlib> #include<string> #include<string.h> #include<cstring> #include<algorithm> #include<vector> #include<map> #include<set> #include<stack> #include<list> #include<queue> #include<ctime> #include<bitset> #include<cmath> #define eps 1e-6 #define INF 0x3f3f3f3f #define PI acos(-1.0) #define ll __int64 #define LL long long #define lson l,m,(rt<<1) #define rson m+1,r,(rt<<1)|1 #define M 1000000007 //#pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; #define Maxn 2200 int n,m; vector<vector<int> >myv; int low[Maxn],dfn[Maxn],sc,bc,dep; int in[Maxn],sta[Maxn]; bool iss[Maxn]; void tarjan(int cur) { int ne; low[cur]=dfn[cur]=++dep; sta[++sc]=cur; iss[cur]=true; for(int i=0;i<myv[cur].size();i++) { ne=myv[cur][i]; if(!dfn[ne]) { tarjan(ne); low[cur]=min(low[cur],low[ne]); } else if(iss[ne]&&dfn[ne]<low[cur]) low[cur]=dfn[ne]; } if(low[cur]==dfn[cur]) { ++bc; do { ne=sta[sc--]; in[ne]=bc; iss[ne]=false; }while(ne!=cur); } } void solve() { sc=bc=dep=0; memset(dfn,0,sizeof(dfn)); memset(iss,false,sizeof(iss)); for(int i=0;i<2*n;i++) if(!dfn[i]) tarjan(i); } int main() { //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); while(~scanf("%d%d",&n,&m)) { myv.clear(); myv.resize(2*n+10); for(int i=1;i<=m;i++) { int a,b,c; char ss[10]; scanf("%d%d%d%s",&a,&b,&c,ss); if(*ss=='A') { if(c==1) { myv[2*a].push_back(2*a+1); myv[2*a+1].push_back(2*b+1); myv[2*b].push_back(2*b+1); myv[2*b+1].push_back(2*a+1); } else { myv[2*a+1].push_back(2*b); myv[2*b+1].push_back(2*a); } } else if(*ss=='O') { if(c==1) { myv[2*a].push_back(2*b+1); myv[2*b].push_back(2*a+1); } else { myv[2*a+1].push_back(2*a); myv[2*a].push_back(2*b); myv[2*b].push_back(2*a); myv[2*b+1].push_back(2*b); } } else { if(c==1) { myv[2*a].push_back(2*b+1); myv[2*a+1].push_back(2*b); myv[2*b].push_back(2*a+1); myv[2*b+1].push_back(2*a); } else { myv[2*a].push_back(2*b); myv[2*a+1].push_back(2*b+1); myv[2*b].push_back(2*a); myv[2*b+1].push_back(2*a+1); } } } solve(); bool ans=true; for(int i=0;i<n;i++) { if(in[2*i]==in[2*i+1]) { ans=false; break; } } if(ans) printf("YES\n"); else printf("NO\n"); } return 0; }