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; }