2-SAT 问题是什么意思,如何求解,大家可以参考 伍昱 的《由对称性解2-SAT问 题》,以及 赵爽 的《2-SAT 解法浅析》两篇论文,很详细,很给力。
hdu3062 Party,裸2-SAT模型,图基本上给好了,判断一下就好。
用 tarjan 算法求强连通,然后判断 b 和 b' 是否在同一个连通分量里面就好。
#include<cstdio>
#include<cstring>
#include<stack>
#include<climits>
using namespace std;
const int N = 2010;
struct Edge{
int s,e,next;
}edge[1000010];
int n,e_num,vis_num,cnt,head[N],instack[N],low[N],tim[N],belong[N];
void AddEdge(int a,int b){
edge[e_num].s=a; edge[e_num].e=b;
edge[e_num].next=head[a]; head[a]=e_num++;
}
void getmap()
{
int m,a,b,c,d;
scanf("%d",&m);
e_num=0;
memset(head,-1,sizeof(head));
while(m--){
scanf("%d%d%d%d",&a,&b,&c,&d);
AddEdge(2*a+c,2*b+(1-d));
AddEdge(2*b+d,2*a+(1-c));
}
}
stack <int>st;
void tarjan(int x){
int i;
tim[x]=low[x]=++vis_num;
instack[x]=1;
st.push(x);
for(i=head[x];i!=-1;i=edge[i].next){
int u=edge[i].e;
if(tim[u]==-1){
tarjan(u);
if(low[x]>low[u])low[x]=low[u];
}
else if(instack[u] && low[x]>tim[u])low[x]=tim[u];
}
if(low[x]==tim[x]){
cnt++;
do{
i=st.top();
st.pop();
instack[i]=0;
belong[i]=cnt;
}while(i!=x);
}
}
void solve(){
int i;
vis_num=cnt=0;
memset(instack,0,sizeof(instack));
memset(belong,-1,sizeof(belong));
memset(tim,-1,sizeof(tim));
memset(low,0,sizeof(low));
for(i=0;i<2*n;i++){
if(tim[i]==-1)tarjan(i);
}
int flag=1;
for(i=0;i<n;i++){
if(belong[2*i]==belong[2*i+1]){
flag=0;break;
}
}
printf(flag?"YES\n":"NO\n");
}
int main()
{
while(~scanf("%d",&n))
{
getmap();
solve();
}
return 0;
}
poj3678 Katu Puzzle,题意是说给出一些变量,他们可以取 0 或 1 ,然后给出一组他们的由 与,或,异或 三种运算组成的式子,问是否有一组可行解,满足这些式子,也是很裸的2-SAT模型,不解释。
#include<cstdio>
#include<cstring>
#include<stack>
#include<climits>
using namespace std;
const int N = 2010;
struct Edge{
int s,e,next;
}edge[N*N];
int n,m,e_num,vis_num,cnt,head[N],instack[N],low[N],tim[N],belong[N];
void AddEdge(int a,int b){
edge[e_num].s=a; edge[e_num].e=b; edge[e_num].next=head[a]; head[a]=e_num++;
}
void getmap()
{
int i,a,b,c;
char ch[3];
e_num=0;
memset(head,-1,sizeof(head));
for(i=0;i<m;i++){
scanf("%d%d%d%s",&a,&b,&c,ch);
if(ch[0]=='A'){
if(c==1){
AddEdge(2*a,2*b+1);
AddEdge(2*a,2*b);
AddEdge(2*a+1,2*b+1);
AddEdge(2*b,2*a+1);
AddEdge(2*b,2*a);
AddEdge(2*b+1,2*a+1);
}
else{
AddEdge(2*a+1,2*b);
AddEdge(2*b+1,2*a);
}
}
else if(ch[0]=='O'){
if(c==1){
AddEdge(2*a,2*b+1);
AddEdge(2*b,2*a+1);
}
else{
AddEdge(2*a,2*b);
AddEdge(2*a+1,2*b+1);
AddEdge(2*a+1,2*b);
AddEdge(2*b,2*a);
AddEdge(2*b+1,2*a+1);
AddEdge(2*b+1,2*a);
}
}
else {
if(c==1){
AddEdge(2*a,2*b+1);
AddEdge(2*a+1,2*b);
AddEdge(2*b,2*a+1);
AddEdge(2*b+1,2*a);
}
else{
AddEdge(2*a,2*b);
AddEdge(2*a+1,2*b+1);
AddEdge(2*b,2*a);
AddEdge(2*b+1,2*a+1);
}
}
}
}
stack <int>st;
void tarjan(int x){
int i;
tim[x]=low[x]=++vis_num;
instack[x]=1;
st.push(x);
for(i=head[x];i!=-1;i=edge[i].next){
int u=edge[i].e;
if(tim[u]==-1){
tarjan(u);
if(low[x]>low[u])low[x]=low[u];
}
else if(instack[u] && low[x]>tim[u])low[x]=tim[u];
}
if(low[x]==tim[x]){
cnt++;
do{
i=st.top();
st.pop();
instack[i]=0;
belong[i]=cnt;
}while(i!=x);
}
}
void solve(){
int i;
vis_num=cnt=0;
memset(instack,0,sizeof(instack));
memset(belong,-1,sizeof(belong));
memset(tim,-1,sizeof(tim));
memset(low,0,sizeof(low));
for(i=0;i<2*n;i++){
if(tim[i]==-1)tarjan(i);
}
int flag=1;
for(i=0;i<n;i++){
if(belong[2*i]==belong[2*i+1]){
flag=0;break;
}
}
printf(flag?"YES\n":"NO\n");
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
getmap();
solve();
}
return 0;
}