[poj 3678]Katu Pazzle[2-SAT常用建图法]
题意:
不说了..典型的2-SAT
常用模型:
重点:
突出"绑定性".
连线表示限制而非可行. 因为最后要求对立点不在同一强连通分量是说同一强连通中的点必须同时选.
坑:
首先是算法记错了...inq是求SPFA用的...
Tarjan中也少了个灰色点黑色点的判断(本身算是查漏补缺吧, 以后检查的时候首先还是看看模板有没有背错)...
分身点加的是点的个数.
异或0的那个判断粗心了...
还是默认多组样例吧...
#include <cstdio> #include <cstring> #include <stack> #include <algorithm> #include <string> #include <iostream> using namespace std; const int MAXN = 1005; const int MAXE = 1000005; struct pool { int v,pre; } p[MAXE<<2]; int n,m; int head[MAXN<<1],num,dfn[MAXN<<1],low[MAXN<<1],id[MAXN<<1],size,Index; bool used[MAXN<<1]; stack<int> s; void clear() { memset(head,0,sizeof(head)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(used,false,sizeof(used)); while(!s.empty()) s.pop(); num = Index = size = 0; } void add(int u, int v) { p[++num].v = v; p[num].pre = head[u]; head[u] = num; } void build(int u, int v, bool c, string s) { if(s=="AND") { if(c) { add(u+n,u); add(v+n,v); } else { add(u,v+n); add(v,u+n); } } else if(s=="OR") { if(c) { add(u+n,v); add(v+n,u); } else { add(u,u+n); add(v,v+n); } } else { if(c) { add(u,v+n); add(v,u+n); add(v+n,u); add(u+n,v); } else { add(u,v); add(u+n,v+n); add(v,u); add(v+n,u+n); } } } void Tarjan(int u) { dfn[u] = low[u] = ++Index; used[u] = true; s.push(u); for(int tmp=head[u],k; k=p[tmp].v,tmp; tmp=p[tmp].pre) { if(!dfn[k]) { Tarjan(k); low[u] = min(low[u],low[k]); } else if(used[k]) low[u] = min(low[u],dfn[k]);//!! } if(dfn[u] == low[u]) { size++; int k; do { k = s.top(); s.pop(); // printf("node = %d size = %d\n",k,size); used[k] = false; id[k] = size; } while(u!=k); } } int main() { while(scanf("%d %d",&n,&m)==2) { string s; bool c; clear(); for(int i = 0,u,v; i<m; i++) { cin>>u>>v>>c>>s; build(u,v,c,s); } for(int i=0; i<n<<1; i++) //每一种状态都要试一遍 { if(!dfn[i]) Tarjan(i); } bool flag = true; for(int i=0; i<n; i++) if(id[i]==id[i+n]) { flag = false; // printf("and %d\n",i); break; } if(flag) printf("YES\n"); else printf("NO\n"); } }