正题
题目链接:http://poj.org/problem?id=3678
题目大意
nnn个xix_ixi为0/10/10/1。有mmm个条件表示xiandxj=ax_i\ and\ x_j=axi and xj=a或xiorxj=ax_i\ or\ x_j=axi or xj=a或xixorxj=ax_i\ xor\ x_j=axi xor xj=a。
求构造一组合法的xix_ixi。
解题思路
讨论一下
- xiandxj=0:x_i\ and\ x_j=0:xi and xj=0:xix_ixi和xjx_jxj不都是111,也就是xix_ixi为111那么xjx_jxj必须为0,反之
- xiandxj=1:x_i\ and\ x_j=1:xi and xj=1:xix_ixi和xjx_jxj都是111,这时候我们就构造矛盾条件xi=0x_i=0xi=0则xi=1x_i=1xi=1限制xi=0x_i=0xi=0即可,xjx_jxj同
- xiorxj=0:x_i\ or\ x_j=0:xi or xj=0:xix_ixi和xjx_jxj都是000,和上面222一样构造即可
- xiorxj=1:x_i\ or\ x_j=1:xi or xj=1:xix_ixi和xjx_jxj不都是000,和上面111一样构造即可
- xixorxj=0:x_i\ xor\ x_j=0:xi xor xj=0:那么xi=0⇒xj=0x_i=0\Rightarrow x_j=0xi=0⇒xj=0且xi=1⇒xj=1x_i=1\Rightarrow x_j=1xi=1⇒xj=1,反之
- xixorxj=1:x_i\ xor\ x_j=1:xi xor xj=1:那么xi=0⇒xj=1x_i=0\Rightarrow x_j=1xi=0⇒xj=1且xi=1⇒xj=0x_i=1\Rightarrow x_j=0xi=1⇒xj=0,反之
时间复杂度O(n)O(n)O(n)
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
using namespace std;
const int N=2100;
struct node{int to,next;
}a[N*4000];
int n,m,tot,num,cnt,ls[N];
int dfn[N],low[N],color[N];
bool ins[N];
stack<int> S;
void addl(int x,int y){a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;return;
}
void tarjan(int x){dfn[x]=low[x]=++cnt;ins[x]=1;S.push(x);for(int i=ls[x];i;i=a[i].next){int y=a[i].to;if(!dfn[y])tarjan(y),low[x]=min(low[x],low[y]);else if(ins[y])low[x]=min(low[x],dfn[y]);}if(dfn[x]==low[x]){++num;while(S.top()!=x){color[S.top()]=num;ins[S.top()]=0;S.pop();}color[S.top()]=num;ins[S.top()]=0;S.pop();}return;
}
int main()
{scanf("%d%d",&n,&m);for(int i=1;i<=m;i++){int a,b,w;char op[4];scanf("%d %d %d %s",&a,&b,&w,op);if(op[0]=='A'){if(w)addl(a,a+n),addl(b,b+n);else addl(b+n,a),addl(a+n,b);}if(op[0]=='O'){if(w)addl(b,a+n),addl(a,b+n);else addl(a+n,a),addl(b+n,b);}if(op[0]=='X'){if(w)addl(a,b+n),addl(b,a+n),addl(a+n,b),addl(b+n,a);else addl(a,b),addl(b,a),addl(a+n,b+n),addl(b+n,a+n);}}for(int i=0;i<2*n;i++)if(!dfn[i])tarjan(i);for(int i=0;i<n;i++)if(color[i]==color[i+n]){printf("NO\n");return 0;}printf("YES\n");return 0;
}