您的位置:首页 > 其它

poj 3678 2-sat(强连通)

2015-05-27 14:34 211 查看
题目链接 poj 3678
Katu Puzzle

Time Limit: 1000MSMemory Limit: 65536K
Total Submissions: 8340Accepted: 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:

AND01
000
101
OR01
001
111
XOR01
001
110
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: