2-SAT模板
用的是刘汝佳大白书里面的版本。网上还有tarjan缩点后再拓扑排序构造解的版本,感觉靠谱一点,但太长了。。。
ps:为什么说“如果当前考虑的变量不管赋值为真还是假都会引起矛盾,可以证明整个2-SAT问题无解”???
是这样的:比如说,某个点探测到的所有点,构成了一个集合。如果有必要调整前面的策略,那就是这个“某个点”探测到的那些点的集合的对立面被访问到了,也就是说,有条边从外面指向里面的点的对立面,然而,如果是这样,那根据图的对称性,这个被指向对立面的里面的某个点也会指向指向他对立面的点的对立面,所以这个指进来的点也属于这个集合,与条件矛盾。---CYC
1 int n; 2 #define maxn ??? 3 struct Edge{int to,next;}; 4 #define maxe ??? 5 struct Graph 6 { 7 Edge edge[maxe];int le; 8 int first[maxn],vis[maxn]; 9 void clear() 10 { 11 le=2; 12 memset(first,0,sizeof(first)); 13 } 14 void insert(int x,int y) 15 { 16 edge[le].to=y; 17 edge[le].next=first[x]; 18 first[x]=le++; 19 } 20 void add_clause(int x,int y) 21 { 22 insert(x^1,y); 23 insert(y^1,x); 24 } 25 int sta[maxn],top; 26 bool dfs(int x) 27 { 28 if (vis[x^1]) return 0; 29 if (vis[x]) return 1; 30 vis[x]=1; 31 sta[++top]=x; 32 for (int i=first[x];i;i=edge[i].next) 33 if (!dfs(edge[i].to)) return 0; 34 return 1; 35 } 36 bool twosat() 37 { 38 memset(vis,0,sizeof(vis)); 39 for (int i=1;i<=n;i++) 40 if (!vis[i*2] && !vis[i*2+1]) 41 { 42 top=0; 43 if (!dfs(i*2)) 44 { 45 for (;top;top--) vis[sta[top]]=0; 46 if (!dfs(i*2+1)) return 0; 47 } 48 } 49 return 1; 50 } 51 }G;