Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 10965 | Accepted: 4063 |
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
Source
一个图,每条边上有一个符号和一个结果,符号是and,or,xor当中的一种,结果是0或1。
要求给每个点分配0或1,使得每条边的两个端点的数值经过对应的符合运算后,结果与要求一致。
一个难点:如何构图使得a and b = 1, a or b = 0 实现。
构图方法:
(take a and b = 1 as an example)
此时两个点均不能取0.
连接a0,a1 b0,b1
这样做是为了导出矛盾。
其余的构图可以从代码中观察到。
奇数点表示0,偶数点表示1.
#include <cstdio>
#include <iostream>
#include <string.h>
#include <string>
#include <map>
#include <queue>
#include <deque>
#include <vector>
#include <set>
#include <algorithm>
#include <math.h>
#include <cmath>
#include <stack>
#include <iomanip>
#define mem0(a) memset(a,0,sizeof(a))
#define meminf(a) memset(a,0x3f,sizeof(a))
using namespace std;
typedef long long ll;
typedef long double ld;
typedef double db;
const int maxn=2005,maxk=2000005,inf=0x3f3f3f3f;
const ll llinf=0x3f3f3f3f3f3f3f3f;
const ld pi=acos(-1.0L);
int head[maxn];
int dfn[maxn],low[maxn],color[maxn];
bool inst[maxn];
int num=0,cnum=0;
stack<int> st;
char s[maxn];
struct Edge {
int from,to,pre;
};
Edge edge[maxk];
void addedge(int from,int to) {
edge[num]=(Edge){from,to,head[from]};
head[from]=num++;
}
void tarjan(int now) {
num++;
dfn[now]=low[now]=num;
inst[now]=1;
st.push(now);
for (int i=head[now];i!=-1;i=edge[i].pre) {
int to=edge[i].to;
if (!dfn[to]) {
tarjan(to);
low[now]=min(low[now],low[to]);
}
else if (inst[to])
low[now]=min(low[now],dfn[to]);
}
if (dfn[now]==low[now]) {
inst[now]=0;
color[now]=++cnum;
while (st.top()!=now) {
color[st.top()]=cnum;
inst[st.top()]=0;
st.pop();
}
st.pop();
}
}
int main() {
int n,m,i,j,x,y,z;
scanf("%d%d",&n,&m);
num=0;
memset(head,-1,sizeof(head));
for (i=1;i<=m;i++) {
scanf("%d%d%d%s",&x,&y,&z,s);
x++;y++;
if (s[0]=='O') {
if (z==1) {
addedge(x*2-1,y*2);
addedge(y*2-1,x*2);
} else {
addedge(x*2,x*2-1);
addedge(y*2,y*2-1);
addedge(x*2-1,y*2-1);
addedge(y*2-1,x*2-1);
}
}
if (s[0]=='A') {
if (z==0) {
addedge(x*2,y*2-1);
addedge(y*2,x*2-1);
} else {
addedge(x*2-1,x*2);
addedge(y*2-1,y*2);
addedge(x*2,y*2);
addedge(y*2,x*2);
}
}
if (s[0]=='X') {
if (z==0) {
addedge(x*2,y*2);
addedge(x*2-1,y*2-1);
addedge(y*2,x*2);
addedge(y*2-1,x*2-1);
} else {
addedge(x*2,y*2-1);
addedge(y*2,x*2-1);
addedge(x*2-1,y*2);
addedge(y*2-1,x*2);
}
}
}
num=0;
mem0(dfn);mem0(low);mem0(color);mem0(inst);
for (i=1;i<=2*n;i++) {
if (!dfn[i]) tarjan(i);
}
for (i=1;i<=n*2;i+=2) {
if (color[i]==color[i+1]) {
printf("NO\n");return 0;
}
}
printf("YES\n");
return 0;
}