POJ 3678 Katu Puzzle【2-SAT】
题意: 有 n 个变元,给出了 m 个他们中的一些元素的关系,问是否存在合法的取值方案。
分析: 典型的2—SAT,在有冲突的取值方案之间连边, x 表是x取真,x+n表示x取假
建图:
a and b ==1 , !a->a , !b -> b
a and b ==0 , a->!b , b->!a
a or b ==1 , !a->b , !b->a
a or b ==0 , a->!a , b->!b
a xor b ==1 , a->!b,!b->a,!a->b,b->!a
a xor b ==0 , a->b,b->a,!a->!b,!b->!a
#include<stdio.h> #include<string.h> #define clr(x)memset(x,0,sizeof(x)) #define maxn 2005 #define min(a,b)(a)<(b)?(a):(b) int dfn[maxn]; int low[maxn]; int sta[maxn]; int col[maxn]; int ins[maxn]; int top,sn,ti; struct node { int to,next; }e[4000000]; int tot; int head[maxn]; void add(int s,int u) { e[tot].to=u; e[tot].next=head[s]; head[s]=tot++; } void tarjan(int u) { dfn[u]=low[u]=++ti; sta[++top]=u; ins[u]=1; int i,k; for(i=head[u];i;i=e[i].next) { k=e[i].to; if(!dfn[k]) { tarjan(k); low[u]=min(low[u],low[k]); } else if(ins[k]) low[u]=min(low[u],dfn[k]); } if(dfn[u]==low[u]) { sn++; do { k=sta[top--]; ins[k]=0; col[k]=sn; } while(k!=u); } } int n; void addedge(int a,int b,int c,char *s) { if(s[0]=='A'){ if(c==1){ add(a+n,a); add(b+n,b); } else{ add(a,b+n); add(b,a+n); } } else if(s[0]=='O'){ if(c==1){ add(a+n,b); add(b+n,a); } else{ add(a,a+n); add(b,b+n); } } else{ if(c==1){ add(a,b+n); add(b+n,a); add(a+n,b); add(b,a+n); } else { add(a,b); add(b,a); add(a+n,b+n); add(b+n,a+n); } } } int main() { int m,i; char op[6]; while(scanf("%d%d",&n,&m)!=EOF) { tot=1; clr(head); while(m--) { int a,b,c; scanf("%d%d%d%s",&a,&b,&c,op); addedge(a,b,c,op); } ti=top=sn=0; clr(dfn); clr(low); clr(ins); clr(col); for(i=0;i<2*n;i++) if(dfn[i]==0) tarjan(i); for(i=0;i<n;i++) if(col[i]==col[i+n]) break; if(i==n) printf("YES\n"); else printf("NO\n"); } return 0; }
 
                    
                     
                    
                 
                    
                

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号