题目:
http://poj.org/problem?id=3678
题意:
有一个n元素的集合, 给出元素之间的关系,(and,or, xor),求出是否满足有满足这样关系的集合.
思路:
2-SAT, 每一个点只能取0/1.
规律: a and b ==1 , !a->a , !b -> b (a=1, b=1)
a and b ==0 , a->!b , b->!a (a=0, b=0)
a or b ==1 , !a->b , !b->a
a or b ==0 , a->!a , b->!b (a=0, b=0)
a xor b ==1 , a->!b,!b->a,!a->b,b->!a ( xor 可以不加边的,因为存在如果a=1,那么b必=0;a=0,b必=1;b=1,a必=0;b=0,a必=1。所以出现a=1时就
a xor b ==0 , a->b,b->a,!a->!b,!b->!a 不会出现a=0的情况,边之间不会矛盾,所以不存在belong[a]=belong[a+n]的情况.另一种说法是形成 自环,a=0,b=1和b=1,a=0.)
AC.
#include <iostream>
#include <cstdio>
#include <cstring>
#include <stack>
using namespace std;
const int MAXN = 20005;
const int MAXM = 2e6+5;
int n, m;
struct edge {
int to, next;
}edge[MAXM];
int head[MAXN], tot;
void init()
{
tot = 0;
memset(head, -1, sizeof(head));
}
void addedge(int u, int v)
{
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
}
int low[MAXN], dfn[MAXN], belong[MAXN];
int scc, Index;
stack<int> S;
void tarjan(int u)
{
int v;
low[u] = dfn[u] = ++Index;
S.push(u);
for(int i = head[u]; i != -1; i = edge[i].next) {
v = edge[i].to;
if(!dfn[v]) {
tarjan(v);
if(low[u] > low[v]) low[u] = low[v];
}
else if(!belong[v] && low[u] > dfn[v]) {
low[u] = dfn[v];
}
}
if(low[u] == dfn[u]) {
scc++;
do {
v = S.top(); S.pop();
belong[v] = scc;
}while(v != u);
}
}
bool solve()
{
memset(dfn, 0, sizeof(dfn));
memset(low, 0, sizeof(low));
memset(belong, 0, sizeof(belong));
Index = scc = 0;
for(int i = 0; i < 2*n; ++i) {
if(!dfn[i]) tarjan(i);
}
for(int i = 0; i < n; ++i) {
if(belong[i] == belong[n+i]) return false;
}
return true;
}
int main()
{
//freopen("in", "r", stdin);
while(~scanf("%d %d", &n, &m)) {
init();
int u, v, d;
char f[5];
for(int i = 0; i < m; ++i) {
scanf("%d %d %d %s", &u, &v, &d, f);
if(f[0] == 'A') {
if(d == 1) {
addedge(n+u, u);
addedge(n+v, v);
}
else {
addedge(u, n+v);
addedge(v, n+u);
}
}
if(f[0] == 'O') {
if(d == 1) {
addedge(n+u, v);
addedge(n+v, u);
}
else {
//addedge(n+u, n+v);
addedge(u, n+u);
addedge(v, n+v);
}
}
// if(f[0] == 'X') {
// if(d == 1) {
// addedge(u, n+v);
// addedge(v, n+u);
// addedge(n+u, v);
// addedge(n+v, u);
// }
// else {
// addedge(n+u, n+v);
// addedge(v+n, n+u);
// addedge(u, v);
// addedge(v, u);
// }
// }
}
if(solve() ) {
printf("YES\n");
}
else printf("NO\n");
}
return 0;
}