本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。
本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!
题目链接:POJ3768
正解:$2-SAT$
解题报告:
$2-SAT$的位运算合集题。仔细想想就能知道连边方式了。
唯一需要注意的就是$AND=1$和$OR=0$相当于是强制赋值,比如$AND=1$就是$x$的$0$直接向$1$连一条边,表示的是$x$不会为$0$。
值得一提的是,必须也要把$x$、$y$连上,开始没注意,$WA$了一发。
//It is made by ljh2000 //有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。 #include <algorithm> #include <iostream> #include <cstring> #include <vector> #include <cstdio> #include <string> #include <queue> #include <cmath> #include <ctime> using namespace std; typedef long long LL; const int MAXN = 10011; const int MAXM = 4000011; int n,m; inline int getint(){ int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar(); if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w; } namespace SAT_2{ int ecnt,first[MAXN],to[MAXM],next[MAXM],top,stack[MAXN],bel[MAXN],scnt,dfn[MAXN],low[MAXN]; bool pd[MAXN]; inline void link(int x,int y){ next[++ecnt]=first[x]; first[x]=ecnt; to[ecnt]=y; } inline void tarjan(int x){ dfn[x]=low[x]=++ecnt; pd[x]=1; stack[++top]=x; for(int i=first[x];i;i=next[i]) { int v=to[i]; if(!dfn[v]) { tarjan(v); low[x]=min(low[x],low[v]); } else if(pd[v]) low[x]=min(low[x],low[v]); } if(dfn[x]==low[x]) { scnt++; while(stack[top]!=x) { bel[stack[top]]=x; pd[x]=0; top--; } pd[x]=0; bel[x]=scnt; top--; } } inline void work(){ ecnt=0; for(int i=2;i<=(n<<1)+1;i++) if(!dfn[i]) tarjan(i); for(int i=1;i<=n;i++) if(bel[i<<1]==bel[i<<1|1]) { puts("NO"); return ; } puts("YES"); } } inline void work(){ using namespace SAT_2; n=getint(); m=getint(); int x,y,z; char c; for(int i=1;i<=m;i++) { x=getint()+1; y=getint()+1; x<<=1; y<<=1; z=getint(); c=getchar(); while(c!='A' && c!='O' && c!='X') c=getchar(); if(c=='A') {//AND if(z==1) {//强制都选1 link(x,x|1); link(y,y|1); link(x|1,y|1); link(y|1,x|1);//!!!必不可少 } else { link(x|1,y); link(y|1,x); } } else if(c=='O') {//OR if(z==1) { link(x,y|1); link(y,x|1); } else {//强制都选0 link(x|1,x); link(y|1,y); link(x,y); link(y,x); } } else {//XOR if(z==1) { link(x,y|1); link(y|1,x); link(x|1,y); link(y,x|1); } else { link(x,y); link(y,x); link(x|1,y|1); link(y|1,x|1); } } } SAT_2::work(); } int main() { #ifndef ONLINE_JUDGE freopen("3768.in","r",stdin); freopen("3768.out","w",stdout); #endif work(); return 0; } //有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。