POJ 3678 Katu Puzzle

    技术2024-07-23  17

    经典2-SAT问题

     

    构图时,根据条件找可以确定关系的形如A->B这样的关系式

     

    i表示i取1,~i表示i取0

     

    i AND j =1    ~i->i, ~j->j, i->j, j->i,后面两个关系式构成一个环,i,j在同一强连通分量中,可以免去

    i AND j = 0   i->~i, j->~j 而~i推不出j为0还是1

    i OR   j =1    ~i->j, ~j->i

    i OR   J =0    i->~i,  j->~j, ~j->~i, ~i->~j 又有环,可以省略

    i XOR j =1    i->~j,  j->~i,  ~i->j,  ~j->i

    i XOR j =0    i->j,  j->i,  ~i->~j, ~j->~i   又构成两个环

     

    代码:

    #include<iostream> #include<stack> using namespace std; const int MAX=2005; const int inf=1<<30; struct node { int v,next; }g[MAX*MAX]; int adj[MAX],low[MAX],dfn[MAX],bel[MAX],inStack[MAX]; int n,m,e,index,cnt,c; char oper[5]; stack<int>s; void add(int u,int v) { g[e].v=v; g[e].next=adj[u]; adj[u]=e++; } void tarjan(int u) { dfn[u]=low[u]=++index; s.push(u); inStack[u]=1; int i,v; for(i=adj[u];i!=-1;i=g[i].next) { v=g[i].v; if(!dfn[v]) { tarjan(v); low[u]=min(low[u],low[v]); } else if(inStack[v]) low[u]=min(low[u],dfn[v]); } if(dfn[u]==low[u]) { cnt++; do { v=s.top(); s.pop(); inStack[v]=0; bel[v]=cnt; }while(u!=v); } } int main() { int i,j; scanf("%d%d",&n,&m); e=index=cnt=0; memset(adj,-1,sizeof(adj)); memset(dfn,0,sizeof(dfn)); //cout<<m<<endl; while(m--) { scanf("%d%d%d%s",&i,&j,&c,&oper); if(oper[0]=='A') { if(c) { add(2*i+1,2*i); add(2*j+1,2*j); //add(2*i,2*j);//2*i和2*j在同一个环中,肯定满足 //add(2*j,2*i); } else { add(2*i,2*j+1); add(2*j,2*i+1); } } else if(oper[0]=='O') { if(c) { add(2*i+1,2*j); add(2*j+1,2*i); } else { add(2*i,2*i+1); add(2*j,2*j+1); //add(2*i+1,2*j+1);//同上 //add(2*j+1,2*i+1); } } else { if(c) { add(2*i,2*j+1); add(2*i+1,2*j); add(2*j,2*i+1); add(2*j+1,2*i); } else { //add(2*i,2*j); //add(2*j,2*i); //add(2*i+1,2*j+1); //add(2*j+1,2*i+1); } } } for(i=0;i<2*n;i++) { if(!dfn[i]) tarjan(i); } int flag=1; for(i=0;i<n;i++) if(bel[2*i]==bel[2*i+1]) { flag=0; break; } if(flag) puts("YES"); else puts("NO"); return 0; }  

     

    最新回复(0)