2sat 问题的练习这个博客收集很多:http://www.cnblogs.com/ambition/archive/2011/07/30/2-sat.html
hdu 3062:裸的,(基本的2选一,限制的2选1,如果能在限制的条件下实现基本的2选1表示题目有解),代码如下:
#include<stdio.h>
#include<string.h>
struct E
{
int t,next;
}edge[200010];
int ant,head[20000];
void init()
{
ant=0;
memset(head,-1,sizeof(head));
}
void add(int a,int b)
{
edge[ant].t=b;
edge[ant].next=head[a];
head[a]=ant++;
}
int vis[20000],sta[20000],sp,n;
int check(int root)
{
if(vis[root^1]) return 0;
if(vis[root]) return 1;
sta[sp++]=root;
vis[root]=1; int i;
for(i=head[root];i!=-1;i=edge[i].next)
if(check(edge[i].t)==0) return 0;
return 1;
}
int dfs(void)
{
int i;
memset(vis,0,sizeof(vis));
for(i=1;i<=n;i++)
{
if(vis[2*i]||vis[2*i+1]) continue;
sp=0;
if(!check(2*i)){
while(sp>0) vis[sta[--sp]]=0;
if(!check(2*i+1)) return 0;
}
}
return 1;
}
int main()
{
int m,i,a1,a2,c1,c2;
while(scanf("%d%d",&n,&m)!=EOF)
{
init();
for(i=1;i<=m;i++){
scanf("%d%d%d%d",&a1,&a2,&c1,&c2);a1++;a2++;
a1=2*a1+c1;a2=2*a2+c2;
add(a1,a2^1);
add(a2,a1^1);
}
puts(dfs()?"YES":"NO");
}
return 0;
}
hdu 1824:也是裸的,把一个队的队长和队员看成是基本的2选1,后面的为限制的2选1,解法和上一题差不多;
#include<stdio.h>
#include<string.h>
struct E
{
int t,next;
}edge[200010];
int ant,head[12001];
void init()
{
ant=0;
memset(head,-1,sizeof(head));
}
void add(int a,int b)
{
edge[ant].t=b;
edge[ant].next=head[a];
head[a]=ant++;
}
int vis[12001],sta[12001],sp,n;
int check(int root)
{
if(vis[root^1]) return 0;
if(vis[root]) return 1;
sta[sp++]=root;
vis[root]=1; int i;
for(i=head[root];i!=-1;i=edge[i].next)
if(check(edge[i].t)==0) return 0;
return 1;
}
int dfs(void)
{
int i;
memset(vis,0,sizeof(vis));
for(i=0;i<=n;i++)
{
if(vis[2*i]||vis[2*i+1]) continue; sp=0;
if(!check(2*i)){
while(sp>0) vis[sta[--sp]]=0;
if(!check(2*i+1)) return 0;
}
}
return 1;
}
int id[3001];
int main()
{
int m,i,a,b,c;
while(scanf("%d%d",&n,&m)!=EOF)
{
init();
for(i=1;i<=n;i++)
{
scanf("%d%d%d",&a,&b,&c);
id[a]=i*2;
id[b]=id[c]=i*2+1;
}
for(i=1;i<=m;i++){
scanf("%d%d",&a,&b);
add(id[a],id[b]^1);
add(id[b],id[a]^1);
}
puts(dfs()?"yes":"no");
}
return 0;
}