2012长春现场赛的题
正解要枚举32个bit,每次做2sat判断是否矛盾
#include <cstdio> #include <cstring> #include <algorithm> #define N 510 #define NN 1010 #define M 3000100 using namespace std; int n,b[N][N]; int head[NN],cnt,scc,top,Index; int dfn[NN],low[NN],instack[NN],sstack[NN],belong[NN]; struct Edge{ int v,next; }edge[M]; void addedge(int u,int v){ edge[cnt].v=v; edge[cnt].next=head[u]; head[u]=cnt++; } void init(){ memset(head,-1,sizeof(head)); memset(instack,0,sizeof(instack)); memset(dfn,0,sizeof(dfn)); cnt=Index=top=scc=0; } void tarjan(int u){ dfn[u]=low[u]=++Index; sstack[++top]=u; instack[u]=1; for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].v; if(dfn[v]==0){ tarjan(v); low[u]=min(low[v],low[u]); } else if(instack[v]) low[u]=min(low[u],dfn[v]); } if(low[u]==dfn[u]){ scc++; while(1){ int tmp=sstack[top--]; instack[tmp]=0; belong[tmp]=scc; if(tmp==u)break; } } } int main(){ int i,j,k; while(scanf("%d",&n)!=EOF){ for(i=0;i<n;i++) for(j=0;j<n;j++) scanf("%d",&b[i][j]); int tem=n; bool ok=1; for(k=0;k<31;k++){ init(); for(i=0;i<n;i++) for(j=i+1;j<n;j++){ if(i%2==1 && j%2==1){ if(b[i][j] & (1<<k)){ addedge(i,j+tem); addedge(j,i+tem); } else{ addedge(i+tem,i); addedge(j+tem,j); } } else if(i%2==0 && j%2==0){ if(b[i][j] & (1<<k)){ addedge(i,i+tem); addedge(j,j+tem); } else{ addedge(i+tem,j); addedge(j+tem,i); } } else{ if(b[i][j] & (1<<k)){ addedge(i,j+tem); addedge(i+tem,j); addedge(j,i+tem); addedge(j+tem,i); } else{ addedge(i,j); addedge(i+tem,j+tem); addedge(j,i); addedge(j+tem,i+tem); } } } for(i=0;i<tem*2;i++) if(!dfn[i]) tarjan(i); bool flag=1; for(i=0;i<tem;i++) if(belong[i]==belong[i+tem]){ flag=0; break; } if(flag==0){ ok=0;break; } } if(ok) printf("YES\n"); else printf("NO\n"); } return 0; }
作者:waitfor_ 发表于2013-3-19 23:47:18 原文链接
阅读:43 评论:0 查看评论