POJ 3678 2-SAT

来源:互联网 发布:此情唯有落花知txt 编辑:程序博客网 时间:2024/04/28 23:46

因为A和B的取值只有0,1,在运算里就可以用2-SAT来解决。

建图过程如下:

1) X AND Y=1,Add(I',J'),Add(J',I'),Add(I,I'),Add(J,J')

2) X AND Y=0,Add(I',J),Add(J',I)

3) X OR Y=1,Add(I,J'),Add(J,I')

4) X OR Y=0,Add(I,J),Add(J,I),Add(I',I),Add(J',J)

5) X XOR Y=1,Add(I',J),Add(J',I),Add(I,J'),Add(J,I')

6) X XOR Y=0,Add(I',J'),Add(J',I'),Add(I,J),Add(J,I)


一开始我没理解红色部分的建图。后来我才知道,如果没有红色部分,那么有一部分的冲突就没有解决。比如:样例里同时有A OR B = 0, A OR B = 1。如果没有下面两句话,Add(I',I),Add(J',J),那么程序是判断不出冲突的,因为在建图的时候就只有A<->B,A -> B', B -> A'。A和A’,B和B‘并不在一个强连通分量里,所以无法判别冲突,画个图看一下就知道了。

对于红色部分更好的解释应该是:X OR Y的时候,X或Y任何一个不能为1,否则就会有冲突,因此从X'和Y'向X, Y连接一条边。


Code:

#include<iostream>#include<cstring>#include<cstdio>#include<algorithm>using namespace std;const int maxn = 2222;const int maxm = 2222222;struct node{    int v, next;}edge[maxm];int head[maxn], k, n, m;int low[maxn], dfn[maxn], belong[maxn], inde, cnt;int stack[maxn << 2], top;bool instack[maxn];void add_edge(int u, int v){    edge[k].v = v, edge[k].next = head[u];    head[u] = k ++;}void tarjan(int u){    int v;    dfn[u] = low[u] = inde ++;    instack[u] = true;    stack[top ++] = u;    for(int i = head[u]; i != -1; i = edge[i].next)    {        v = edge[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(low[u] == dfn[u])    {        cnt ++;        do{            v = stack[-- top];            instack[v] = false;            belong[v] = cnt;            num[cnt] ++;        }while(v != u);    }}int main(){    while(~scanf("%d%d", &n, &m))    {        memset(head, -1, sizeof(head));        k = 0;        while(m --)        {            int u, v, val;            char op[10];            scanf("%d%d%d%s", &u, &v, &val, op);            if(op[0] == 'A')            {                if(val == 0)                {                    add_edge(u + n, v);                    add_edge(v + n, u);                }                else                {                    add_edge(u + n, v + n);                    add_edge(v + n, u + n);                    add_edge(u, u + n);  //   u can't be 0                    add_edge(v, v + n);  //   v can't be 0                }            }            else if(op[0] == 'O')            {                if(val == 0)                {                    add_edge(u, v);                    add_edge(v, u);                    add_edge(u + n, u);  //   u can't be 1                    add_edge(v + n, v);  //   v can't be 1                }                else                {                    add_edge(u, v + n);                    add_edge(v, u + n);                }            }            else if(op[0] == 'X')            {                if(val == 0)                {                    add_edge(u, v);                    add_edge(v, u);                    add_edge(u + n, v + n);                    add_edge(v + n, u + n);                }                else                {                    add_edge(u, v + n);                    add_edge(v, u + n);                    add_edge(v + n, u);                    add_edge(u + n, v);                }            }        }        memset(dfn, 0, sizeof(dfn));        memset(instack, false, sizeof(instack));        top = 0, cnt = 0, inde = 1;        int nn = 2 * n;        for(int i = 0; i < nn; i ++)            if(!dfn[i])                tarjan(i);        bool ok = true;        for(int i = 0; i < nn; i ++)            if(belong[i] == belong[i + n])                ok = false;        if(!ok)            printf("NO\n");        else            printf("YES\n");           }}






原创粉丝点击