poj3867(2-sat)

来源:互联网 发布:软件详细设计模板 java 编辑:程序博客网 时间:2024/06/17 09:56

题目大意:

                 给了N个点和M条边,每个点的权值可以是0可以是1,M条边有一个边权和一个操作,问是否存在一个点权赋值方式,满足m条边的两个端点的权值通过该边的操作和该边的权值相等。挑战上经典的2-sat问题。

列出一个真值表,看着建图就行了。

#include<cstdio>#include<cstring>#include<algorithm>#include<stack>using namespace std;const int maxn = 1000+10;struct node{    int to;    int next;    node(){}    node(int a,int b):to(a),next(b){}}edge[4000005];int head[maxn*2],dfn[maxn*2],low[maxn*2],vis[maxn*2],cnt,ti,clo[maxn];int tot;stack<int>s;void add_edge(int u,int v){    edge[tot] = node(v,head[u]);    head[u] = tot++;}void tarjan(int u){    dfn[u] = low[u] = ++ti;    vis[u] = 1; s.push(u);    for(int i=head[u];i!=-1;i=edge[i].next)    {        int v = edge[i].to;        if(!dfn[v])        {            tarjan(v);            low[u] = min(low[u],low[v]);        }        else if(vis[v]==1)            low[u] = min(low[u],dfn[v]);    }    if(low[u]==dfn[u])    {        int y; cnt++;        do{            y = s.top(); s.pop();            clo[y] = cnt; vis[y] = 2;        }while(y!=u);    }}int main(){    int n,m,a,b,c;    char op[5];    while(scanf("%d%d",&n,&m)!=EOF)    {        tot = 0; memset(head,-1,sizeof(head));        for(int i=0;i<m;i++)        {            scanf("%d%d%d%s",&a,&b,&c,op);            if(op[0]=='A')            {                if(c==1){                    add_edge(2*a,2*a+1);                    add_edge(b*2,2*b+1);                }else{                    add_edge(2*a+1,2*b);                    add_edge(2*b+1,2*a);                }            }            else if(op[0]=='O')            {                if(c==1)                {                    add_edge(2*a,b*2+1);                    add_edge(2*b,2*a+1);                }                else                {                    add_edge(2*a+1,2*a);                    add_edge(2*b+1,2*b);                }            }            else if(op[0]=='X')            {                if(c==1)                {                    add_edge(2*a,2*b+1);                    add_edge(2*a+1,2*b);                    add_edge(2*b,2*a+1);                    add_edge(2*b+1,2*a);                }                else                {                    add_edge(2*a,2*b);                    add_edge(2*a+1,2*b+1);                    add_edge(2*b,2*a);                    add_edge(2*b+1,2*a+1);                }            }        }        memset(dfn,0,sizeof(dfn));        memset(low,0,sizeof(low));        memset(vis,0,sizeof(vis));        cnt = 0; ti = 0; int f = 1;        for(int i=0;i<2*n;i++) if(!dfn[i]) tarjan(i);        for(int i=0;i<n;i++)            if(clo[2*i]==clo[i*2+1]) { f=0;break; }        if(f) puts("YES");        else puts("NO");    }    return 0;}



原创粉丝点击