POJ 3678 Katu Puzzle 2-sat
http://poj.org/problem?id=3678
题意:给出n个数和m组数对应的位运算,判断n个数是否满足m组位运算
构图:把每个点拆成两个,一个代表0,一个代表1,总共有2*n个点,0~2*n-1
a AND b=0 2*a+1->2*b , 2*b+1->2*a
a AND b=1 2*a->2*a+1 , 2*b->2*b+1 (AND 1 时 要求a和b同时为1,
不能为0的处理时:如果i取0,那么i就要取1.)
其它的类似
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<string> #define Min(a,b)a<b?a:b #define nMAX 2010 #define mMAX 2000010 int head[nMAX],sta[nMAX],dfn[nMAX],low[nMAX],belon[nMAX]; int s_edge,atype,top,times,n; bool insta[nMAX]; struct Edge { int to,next; }edge[mMAX]; void addedge(int u,int v) { s_edge++; edge[s_edge].to=v; edge[s_edge].next=head[u]; head[u]=s_edge; return; } void tarjan(int u) { dfn[u]=++times; low[u]=times; insta[u]=1; sta[++top]=u; for(int e=head[u];e;e=edge[e].next) { int v=edge[e].to; if(!dfn[v]) { tarjan(v); low[u]=Min(low[u],low[v]); } else if(insta[v]) low[u]=Min(low[u],dfn[v]); } int j; if(dfn[u]==low[u]) { atype++; do { j=sta[top--]; insta[j]=0; belon[j]=atype; }while(j!=u); } return ; } bool judge() { for(int i=0;i<2*n;i+=2) { if(belon[i]==belon[i+1]) return false; } return true; } void init() { s_edge=0; times=0; top=0; atype=0; memset(head,0,sizeof(head)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(sta,0,sizeof(sta)); memset(insta,0,sizeof(insta)); memset(belon,0,sizeof(belon)); return ; } int main() { int m,i,j,k; char ch[5]; while(~scanf("%d%d",&n,&m)) { init(); while(m--) { scanf("%d%d%d%s",&i,&j,&k,ch); if(ch[0]=='A') { if(k==0) { addedge(2*i+1,2*j); addedge(2*j+1,2*i); } else if(k==1) { addedge(2*i,2*i+1); addedge(2*j,2*j+1); } } if(ch[0]=='O') { if(k==0) { addedge(2*i+1,2*i); addedge(2*j+1,2*j); } else if(k==1) { addedge(2*i,2*j+1); addedge(2*j,2*i+1); } } if(ch[0]=='X') { if(k==0) { addedge(2*i,2*j); addedge(2*j,2*i); addedge(2*i+1,2*j+1); addedge(2*j+1,2*i+1); } else if(k==1) { addedge(2*i,2*j+1); addedge(2*j+1,2*i); addedge(2*i+1,2*j); addedge(2*j,2*i+1); } } } for(i=0;i<2*n;i++) if(!dfn[i])tarjan(i); if(judge())printf("YES\n"); else printf("NO\n"); } return 0; }