【题意】
这个函数是给A求B的,现在给你B,问你是否能有A的解存在。
【2-SAT解法】
对于每个A[i]的每一位运行2-sat算法,只要跑到强连通就可以结束,应为只要判断是否有解,后面拓扑求解就不需要了。构图和算法思想和基本的2-sat一致,详见我的2-sat博文。
1 #include <stdio.h> 2 #include <string.h> 3 inline int min(int a,int b){return a>b?b:a;} 4 struct edge 5 { 6 int v,next; 7 edge(int d=0,int n=-1):v(d),next(n){} 8 void set(int d,int n){v=d;next=n;} 9 }data[500*2001]; 10 int head[1024],hn; 11 void adde(int a,int b) 12 { 13 data[hn].set(b,head[a]); 14 head[a]=hn++; 15 } 16 int n; 17 int b[501][501]; 18 int dfn[1024],low[1024],sta[1024],belong[1024]; 19 bool ifin[1024]; 20 int top,group,dep; 21 void tarjan(int u) 22 { 23 dfn[u]=low[u]=++dep; 24 sta[++top]=u; 25 ifin[u]=true; 26 for (int i=head[u];i!=-1;i=data[i].next) 27 { 28 int v=data[i].v; 29 if (!dfn[v]) 30 { 31 tarjan(v); 32 low[u]=min(low[u],low[v]); 33 } else 34 { 35 if (ifin[v]) low[u]=min(low[u],dfn[v]); 36 } 37 } 38 if (dfn[u]==low[u]) 39 { 40 int j; 41 ++group; 42 do 43 { 44 j=sta[top--]; 45 belong[j]=group; 46 ifin[j]=false; 47 } while (u!=j); 48 } 49 } 50 void init() 51 { 52 hn=dep=group=0; 53 top=-1; 54 memset(head,-1,sizeof head); 55 memset(dfn,0,sizeof dfn); 56 memset(ifin,false,sizeof ifin); 57 } 58 bool judge() 59 { 60 for (int i=0;i<n;++i) 61 if (belong[i]==belong[i+n]) return false; 62 return true; 63 } 64 bool solve() 65 { 66 for (int i=0;i<n;++i) 67 for (int j=i;j<n;++j) 68 { 69 if (i==j && b[i][j]) return false; 70 if (b[i][j]!=b[j][i]) return false; 71 } 72 for (int k=0;k<31;++k) 73 { 74 init(); 75 for (int i=0;i<n;++i) 76 for (int j=i;j<n;++j) 77 { 78 int m=b[i][j]&(1<<k); 79 if (i==j) continue; 80 if (i&1 && j&1) // | 81 { 82 if (m) 83 { 84 adde(i,j+n); 85 adde(j,i+n); 86 } else 87 { 88 adde(i+n,i); 89 adde(j+n,j); 90 } 91 } else if (!(i&1) && !(j&1)) //& 92 { 93 if (m) 94 { 95 adde(i,i+n); 96 adde(j,j+n); 97 } else 98 { 99 adde(i+n,j); 100 adde(j+n,i); 101 } 102 } else // ^ 103 { 104 if (m) 105 { 106 adde(i,j+n); 107 adde(j,i+n); 108 adde(j+n,i); 109 adde(i+n,j); 110 } else //== 111 { 112 adde(i,j); 113 adde(j,i); 114 adde(i+n,j+n); 115 adde(j+n,i+n); 116 } 117 } 118 } 119 for (int i=0;i<(n<<1);++i) 120 if (!dfn[i]) tarjan(i); 121 if (!judge()) return false; 122 } 123 return true; 124 } 125 int main() 126 { 127 while (~scanf("%d",&n)) 128 { 129 for (int i=0;i<n;++i) 130 for (int j=0;j<n;++j) 131 scanf("%d",&b[i][j]); 132 if (solve()) puts("YES"); else puts("NO"); 133 } 134 }