题目大意
给你几个二进制运算的结果,求是否有解。
试题分析
$2-SAT$板子吧,其实主要就是在$2-SAT$中我们连边是对于选择$u$点后必须选择$v$点才连$(u,v)$。
然后就$tarjan$判断两点是否在一个强连通分量中。
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> using namespace std; inline int read(){ int f=1,ans=0;char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();} return f*ans; } const int N=2001; const int M=1000001; int n,m; char str[11]; struct node{ int u,v,nex; }x[M<<4]; int head[N<<4],cnt; void add(int u,int v){ x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],head[u]=cnt++; } int dfn[N],low[N],tot,co[N],col,num,sta[N]; void tarjan(int f){ dfn[f]=low[f]=++num; sta[++tot]=f; for(int i=head[f];i!=-1;i=x[i].nex){ if(!dfn[x[i].v]){ tarjan(x[i].v); low[f]=min(low[f],low[x[i].v]); }else if(!co[x[i].v]) low[f]=min(low[f],dfn[x[i].v]); } if(low[f]==dfn[f]){ co[f]=++col; while(sta[tot]!=f){ co[sta[tot]]=col; tot--; }tot--; return; } } bool query(){ for(int i=1;i<=n;i++) if(co[i]==co[i+n]) return 0; return 1; } int main(){ while(~scanf("%d%d", &n, &m)){ cnt=0,col=0,tot=0; memset(head,-1,sizeof(head)),memset(co,0,sizeof(co)),memset(dfn,0,sizeof(dfn)),memset(low,0,sizeof(low)); for(int i=1;i<=m;i++){ int u=read(),v=read(),c=read();scanf("%s",str+1); u++,v++; if(str[1]=='A'){ if(c==0) add(u+n,v),add(v+n,u); else add(u,u+n),add(v,v+n); } if(str[1]=='O'){ if(c==0) add(u+n,u),add(v+n,v); else add(u,v+n),add(v,u+n); } if(str[1]=='X'){ if(c==0) add(u,v),add(v,u),add(u+n,v+n),add(v+n,u+n); else add(u,v+n),add(v+n,u),add(u+n,v),add(v,u+n); } } for(int i=1;i<=2*n;i++) if(!dfn[i]) tarjan(i); if(query()) printf("YES "); else printf("NO "); } }