• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

POJ 3678 Katu Puzzle(2

mysql 搞代码 4年前 (2022-01-09) 34次浏览 已收录 0个评论

POJ 3678 Katu Puzzle(2-SAT) http://poj.org/problem?id=3678 题意: 一个N个顶点和M条边的有向图,每个顶点能取0或1两个.现在每条边被一个操作符(or,and,xor)以及一个(0或1)标记了,表示a与b按操作符运算的结果是(0或1).问你该有向图是否有可行解? 分析: 由于

POJ 3678 Katu Puzzle(2-SAT)

http://poj.org/problem?id=3678

题意:

本文来源gao.dai.ma.com搞@代*码#网 一个N个顶点和M条边的有向图,每个顶点能取0或1两个值.现在每条边被一个操作符(or,and,xor)以及一个值(0或1)标记了,表示a与b按操作符运算的结果是值(0或1).问你该有向图是否有可行解?

分析:

由于每个点只能取0或1两个值,所以我们把该问题转化为2-SAT问题.原图中的每个点对应2-SAT中的每个点.对于每种运算有下列转换方式:

a and b = 0 转换为 a=0 或 b=0

a and b = 1 转换为 a=1 且 b=1 即添加边 2*a->2*a+1 2*b->2*b+1(只要a0b0必然引起矛盾)

a or b = 0 转换为 2*a+1->2*a 2*b+1->2*b(只要a1b1必然引起矛盾)

a or b = 1 转换为 a=1 或b=1

a xorb=0转换为 a=1且b=1 或 a=0且b=0 即连下面的边:

2*a->2*b 2*b->2*a 2*a+1->2*b+1 2*b+1->2*a+1.

a xor b=1 转换为a=1且b=0 或a=0且b=1 则连下面的边:

2*a+1->2*b 2*b->2*a+1 2*a->2*b+1 2*b+1->2*a

AC代码:

#include#include#include#includeusing namespace std;const int maxn=1000+10;struct TwoSAT{    int n;    vector G[maxn*2];    int S[maxn*2],c;    bool mark[maxn*2];    bool dfs(int x)    {        if(mark[x^1]) return false;        if(mark[x]) return true;        mark[x]=true;        S[c++]=x;        for(int i=0;in=n;        for(int i=0;i<n*2;i++) G[i].clear();        memset(mark,0,sizeof(mark));    }    void add_clause(int x,int xval,int y,int yval)//这里的函数做了修改,只加单向边    {        x=x*2+xval;        y=y*2+yval;        G[x].push_back(y);    }    bool solve()    {        for(int i=0;i0) mark[S[--c]]=false;                if(!dfs(i+1)) return false;            }        }        return true;    }}TS;int main(){    int n,m;    scanf("%d%d",&n,&m);    TS.init(n);    int a,b,c;    char op[10];    for(int i=0;i<m;i++)    {        scanf("%d%d%d%s",&a,&b,&c,op);        if(op[0]=='A')        {            if(c==0)            {                TS.add_clause(a,1,b,0);                TS.add_clause(b,1,a,0);            }            else if(c==1)            {                TS.add_clause(a,0,a,1);                TS.add_clause(b,0,b,1);            }        }        else if(op[0]=='O')        {            if(c==0)            {                TS.add_clause(a,1,a,0);                TS.add_clause(b,1,b,0);            }            else if(c==1)            {                TS.add_clause(a,0,b,1);                TS.add_clause(b,0,a,1);            }        }        else if(op[0]=='X')        {            if(c==0)            {                TS.add_clause(a,0,b,0);                TS.add_clause(a,1,b,1);                TS.add_clause(b,0,a,0);                TS.add_clause(b,1,a,1);            }            else if(c==1)            {                TS.add_clause(a,0,b,1);                TS.add_clause(a,1,b,0);                TS.add_clause(b,0,a,1);                TS.add_clause(b,1,a,0);            }        }    }    if(TS.solve()) printf("YES\n");    else printf("NO\n");    return 0;}

搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:POJ 3678 Katu Puzzle(2

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址