poj3678(two-sat)

传送门:Katu Puzzl

题意:n个点,点的取值可以是0或者1。m条边,有权值,有运算方式(并,或,异或),要求和这条边相连的两个点经过边上的运算后的结果是边的权值。问你有没有可能把每个点赋值满足所有边的要求。

分析:每个点必须取一个值满足所有限制条件,明显的two-sat模型。

AND 结果为1:建边 ~a->a,~b->b (两个数必须全为1)

AND 结果为0:建边 b->~a,a->~b (两个数至少有一个为0)

OR 结果为1:建边 ~a->b,~b->a (两个数至少有一个为1)

OR 结果为0:建边 a->~a,b->~b (两个数必须全为0)

XOR 结果为1:建边 a->~b,b->~a,~b->a,~a->b (两个数必须不同)

XOR 结果为0:建边 a->b,b->a,~a->~b,~b->~a (两个数必须相同)

#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdlib>
#include <stack>
#include <vector>
#include <set>
#include <map>
#define LL long long
#define mod 100000000
#define inf 0x3f3f3f3f
#define eps 1e-6
#define N 2010
#define FILL(a,b) (memset(a,b,sizeof(a)))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define PII pair<int,int>
using namespace std;
struct edge
{
    int v,next;
    edge() {}
    edge(int v,int next):v(v),next(next) {}
} e[N*N/2];
int n,m,scc,step,top,tot;
int head[N],dfn[N],low[N],belong[N],Stack[N];
bool instack[N];
void init()
{
    tot=0;step=0;
    scc=0;top=0;
    FILL(head,-1);
    FILL(dfn,0);
    FILL(low,0);
    FILL(instack,false);
}
void addedge(int u,int v)
{
    e[tot]=edge(v,head[u]);
    head[u]=tot++;
}
void tarjan(int u)
{
    int v;
    dfn[u]=low[u]=++step;
    Stack[top++]=u;
    instack[u]=true;
    for(int i=head[u]; ~i; i=e[i].next)
    {
        v=e[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])
    {
        scc++;
        do
        {
            v=Stack[--top];
            instack[v]=false;
            belong[v]=scc;
        }
        while(v!=u);
    }
}

void solve()
{
    for(int i=0; i<2*n; i++)
        if(!dfn[i])tarjan(i);
    bool flag=true;
    for(int i=0; i<n; i++)
    {
        if(belong[i<<1]==belong[i<<1^1])
        {
            flag=false;
            break;
        }
    }
    if(flag)puts("YES");
    else puts("NO");
}
int main()
{
    int a,b,c,u,v;
    char op[10];
    while(scanf("%d%d",&n,&m)>0)
    {
        init();
        for(int i=0;i<m;i++)
        {
            scanf("%d%d%d%s",&a,&b,&c,op);
            if(op[0]==‘A‘)
            {
                if(c)
                {
                    addedge(a<<1^1,a<<1);
                    addedge(b<<1^1,b<<1);
                }
                else
                {
                    addedge(a<<1,b<<1^1);
                    addedge(b<<1,a<<1^1);
                }
            }
            else if(op[0]==‘O‘)
            {
                if(c)
                {
                    addedge(a<<1^1,b<<1);
                    addedge(b<<1^1,a<<1);
                }
                else
                {

                   addedge(a<<1,a<<1^1);
                   addedge(b<<1,b<<1^1);
                }
            }
            else
            {
                if(c)
                {
                    addedge(a<<1,b<<1^1);
                    addedge(b<<1,a<<1^1);
                    addedge(a<<1^1,b<<1);
                    addedge(b<<1^1,a<<1);
                }
                else
                {
                    addedge(a<<1,b<<1);
                    addedge(b<<1,a<<1);
                    addedge(a<<1^1,b<<1^1);
                    addedge(b<<1^1,a<<1^1);
                }
            }
        }
        solve();
    }
}

时间: 2024-10-14 05:51:11

poj3678(two-sat)的相关文章

LA 3211 飞机调度(2—SAT)

https://vjudge.net/problem/UVALive-3211 题意: 有n架飞机需要着陆,每架飞机都可以选择“早着陆”和“晚着陆”两种方式之一,且必须选择一种,第i架飞机的早着陆时间为E,晚着陆时间为L,不得在其他时间着陆.你的任务是为这些飞机安排着陆方式,使得整个着陆计划尽量安全.换句话说,如果把所有飞机的实际着陆时间按照从早到晚的顺序排列,相邻两个着陆时间间隔的最小值. 思路: 二分查找最大值P,每次都用2—SAT判断是否可行. 1 #include<iostream>

8.3吝啬SAT问题

吝啬SAT问题是这样的:给定一组子句(每个子句都是其中文字的析取)和整数k,求一个最多有k个变量为true的满足赋值--如果该赋值存在.证明吝啬SAT是NP-完全问题. 1.易知吝啬SAT的解可以在多项式时间内验证,因此属于NP问题. 2.如果我们把吝啬SAT问题中的k设置为输入的数目,那么SAT问题就可以规约到吝啬SAT问题,所以吝啬SAT问题是np-完全问题.

POJ 3207 Ikki&#39;s Story IV - Panda&#39;s Trick(2 - sat啊)

题目链接:http://poj.org/problem?id=3207 Description liympanda, one of Ikki's friend, likes playing games with Ikki. Today after minesweeping with Ikki and winning so many times, he is tired of such easy games and wants to play another game with Ikki. liy

多边形碰撞 -- SAT方法

检测凸多边形碰撞的一种简单的方法是SAT(Separating Axis Theorem),即分离轴定理. 原理:将多边形投影到一条向量上,看这两个多边形的投影是否重叠.如果不重叠,则认为这两个多边形是分离的,否则找下一条向量来继续投影.我们不需要比较很多条向量,因为已经在数学上证明,多边形每条边的垂直向量就是我们需要的向量. 1.AABB 让我们首先以AABB开始(AABB是一种两边分别平行于X-Y轴的矩形) 判断两个AABB是否碰撞,我们只需要投影两次,分别是投影在平行于X轴和Y轴的向量上

hdu 4421 和poj3678类似二级制操作(2-sat问题)

/* 题意:还是二进制异或,和poj3678类似 建边和poj3678一样 */ #include<stdio.h> #include<string.h> #include<math.h> #define N 2100 struct node{ int v,next; }bian[N*N]; int head[N],dfn[N],low[N],vis[N],stac[N],belong[N],yong,ans,index,top; void init() { yong=

hdu 4751 Divide Groups 2—sat问题 还是未理解

Divide Groups Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1443    Accepted Submission(s): 512 Problem Description This year is the 60th anniversary of NJUST, and to make the celebration mor

HIT 1917 2—SAT

题目大意:一国有n个党派,每个党派在议会中都有2个代表, 现要组建和平委员会,要从每个党派在议会的代表中选出1人,一共n人组成和平委员会. 已知有一些代表之间存在仇恨,也就是说他们不能同时被选为和平委员会的成员, 现要你判断满足要求的和平委员会能否创立?如果能,请任意给出一种方案.( POI 0106 ) ----------------------------------------- 这道题就是裸的2-SAT 不过我用了tarjan缩点 然后一波拓排 tips:一个问题无解当且仅当一个集合的

2—SAT问题

现有一个由N个布尔值组成的序列A,给出一些限制关系,比如A[x] AND A[y]=0.A[x] OR A[y] OR A[z]=1.A[x] XOR A[y]=0等,要确定A[0..N-1]的值,使得其满足所有限制关系.这个称为SAT问题,特别的,若每种限制关系中最多只对两个元素进行限制,则称为2-SAT问题. 对于x.y有11种关系,将其拆点2x(假),2x+1(真).对于x为假或者y为假这样的条件,我们连两条有向边2x+1->2y.2y+1->2x,注意这里是有向边以及边的起点和终点的关

SAT考试里最难的数学题? &middot; 三只猫的温暖

问题 今天无意中在Quora上看到有人贴出来一道号称是SAT里最难的一道数学题,一下子勾起了我的兴趣.于是拿起笔来写写画画,花了差不多十五分钟搞定.觉得有点意思,决定把解题过程记下来.原帖的图太小,我用GeoGebra重新画了一遍.没错,我就是强迫症. 为了省事,就把这道题叫做RASBTC. In the figure above, arc (text{SBT}) is one quarter of a circle with center (text{R}) and radius 6. If

SAT求解器变元活跃度计算模式的切换

变元活跃度计算模式有:VSIDS.基于历史出现时刻与当前冲突时刻距离等 有三个最小堆: // A priority queue of variables ordered with respect to the variable activity. Heap<VarOrderLt> order_heap_CHB,                                order_heap_VSIDS, order_heap_distance; 一般的求解切换方式是: conflicts