poj 3678 XOR和OR和AND(简单2-sat问题)

/*
题意:给你一些边,每条边有一个值和一个运算符XOR OR  AND求是否存在一些点使得所有的边根据这些运算符
可以符合条件的权值.
建边方式参考:http://blog.csdn.net/shuangde800/article/details/8876533
这种建边方式真好,以后就用这种了
0 --  1
0 --  0
1 --  0
1 --  1
根据预算符有矛盾就建两条边
因为这题中的c只有两种取值0,1,所以只需要计算一次就可以了
*/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
#define N  2100
#define NN  1100000
struct node {
int u,v,w,next;
char s[5];
}bian[NN*8];
int head[N],yong,low[N],dfn[N],belong[N],ans,top,index,stac[N],vis[N];
void init() {
memset(head,-1,sizeof(head));
yong=index=ans=top=0;
memset(vis,0,sizeof(vis));
memset(dfn,0,sizeof(dfn));
}
void addedge(int u,int v) {
bian[yong].v=v;
bian[yong].next=head[u];
head[u]=yong++;
}
void tarjan(int u) {
  low[u]=dfn[u]=++index;
  stac[++top]=u;
  vis[u]=1;
  int i;
  for(i=head[u];i!=-1;i=bian[i].next) {
    int v=bian[i].v;
    if(!dfn[v]) {
        tarjan(v);
        low[u]=min(low[u],low[v]);
    }
    else
    if(vis[v])
        low[u]=min(low[u],dfn[v]);
  }
  if(low[u]==dfn[u]){
    ans++;
    int t;
    do {
        t=stac[top--];
        belong[t]=ans;
        vis[t]=0;
    }while(t!=u);
  }
}
int slove(int n) {
  int i;
  for(i=0;i<n;i++)
    if(!dfn[i])
    tarjan(i);
   // printf("%d\n",ans);
  for(i=0;i<n;i++)
    if(belong[i]==belong[i+n])
    return 0;
  return 1;
}
int main(){
    int n,m,i,u,v,w;
    char s[5];
    while(scanf("%d%d",&n,&m)!=EOF) {
            init();
        for(i=0;i<m;i++) {
            scanf("%d%d%d%s",&u,&v,&w,s);
            if(strcmp(s,"AND")==0) {
          if(w) {
           addedge(u,v);addedge(v+n,u+n);//1,0
           addedge(u+n,v+n);addedge(v,u);//0,1
           addedge(u+n,v);addedge(v+n,u);//0,0
          }
          else {
            addedge(u,v+n);addedge(v,u+n);
          }
            }
          if(strcmp(s,"OR")==0) {
                if(w) {
                    addedge(u+n,v);
                    addedge(v+n,u);
                }
                else {
        addedge(u,v);addedge(v+n,u+n);//1,0
           addedge(u+n,v+n);addedge(v,u);//0,1
           addedge(u,v+n);addedge(v,u+n);//1,1
                }
            }
             if(strcmp(s,"XOR")==0) {
                if(w) {
               addedge(u+n,v);addedge(v+n,u);//0,0
                 addedge(u,v+n);addedge(v,u+n);//1,1
                }
                else {
                         addedge(u,v);addedge(v+n,u+n);//1,0
           addedge(u+n,v+n);addedge(v,u);//0,1
                }
            }
            }
            if(slove(n))
                printf("YES\n");
            else
                printf("NO\n");
    }
return 0;}

时间: 2024-08-27 17:55:31

poj 3678 XOR和OR和AND(简单2-sat问题)的相关文章

poj 3678 2-sat

2-sat经典建图,注意AND为1的时候,a=0要和a=1连边,b同理,因为此时a,b都不能为0. OR为0时候,a=1要和a=0连边,b同理,因为此时a,b都不能为1. #include<iostream> #include<cstdio> #include<cstring> #include<vector> #include<algorithm> #include<cmath> using namespace std; #defi

poj 3678 2-sat(强连通)

题目链接 poj 3678 Katu Puzzle Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8340   Accepted: 3077 Description Katu Puzzle is presented as a directed graph G(V, E) with each edge e(a, b) labeled by a boolean operator op (one of AND, OR, XOR

poj 2193 Lenny&#39;s Lucky Lotto Lists 简单dp

//poj 2193 //sep9 #include <iostream> using namespace std; typedef __int64 INT; INT dp[16][2048]; int n,m; int main() { int cases,t=0; scanf("%d",&cases); while(cases--){ scanf("%d%d",&n,&m); memset(dp,0,sizeof(dp));

POJ 1286 Necklace of Beads(Polya简单应用)

Necklace of Beads 大意:3种颜色的珠子,n个串在一起,旋转变换跟反转变换如果相同就算是同一种,问会有多少种不同的组合. 思路:正规学Polya的第一道题,在楠神的带领下,理解的还算挺快的,代码没什么好说的,裸的Polya,也不需要优化. 1 /************************************************************************* 2 > File Name: POJ1286.cpp 3 > Author: GLSil

POJ 2409 Let it Bead(Polya简单应用)

Let it Bead 大意:给你m种颜色,n个珠子串起来,旋转跟反转相同算相同,问有多少种不同的涂色组合方式. 思路:Polya的简单应用. 1 /************************************************************************* 2 > File Name: POJ2409.cpp 3 > Author: GLSilence 4 > Created Time: 2014年07月29日 星期二 22时56分58秒 5 **

POJ 3678

这道题唯一一个注意的地方是,如出现X\/Y=0这种关系时,X=0,Y=0.已经是可以肯定的关系了,所以可以连边X->-X. 我也错了上面这地方.看来,还不够.以后要细心才好. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <string.h> 5 #include <algorithm> 6 #include <cmath> 7

POJ 1473 There&#39;s Treasure Everywhere!(简单几何)

There's Treasure Everywhere! 博客原文地址:http://blog.csdn.net/xuechelingxiao/article/details/40865611 题目大意: 给你一个字符串,里面有许多的操作,前面的数字是移动的距离,后面的英文表示移动的方向,问最后从远点出发的一个点回落在什么地方以及距离出发点的距离是多少. 解题思路: 题目本身并不是很难,也没有什么坑点,没什么好说的,字符串处理的时候细心一点就行. PS:每组后面需要加一个回车,因为这个PE了一次

POJ 3667 线段树的区间合并简单问题

题目大意:有一排标号1-N的房间.操作一:询问是不是有连续长度为a的空房间,有的话住进最左边(占用a个房间)操作二:将[a,a+b-1]的房间清空(腾出b个房间)思路:记录每个区间中“靠左”“靠右”“中间”的空房间线段树操作:update:区间替换query:询问满足条件的最左端点 题目链接: http://vjudge.net/problem/viewProblem.action?id=10354 题目操作: 因为这里找从最左边住起的房间,所以这里不能像常规地写query函数那样写了,终于发现

POJ 3678 Katu Puzzle(2-sat 模板题)

题目链接:http://poj.org/problem?id=3678 Description Katu Puzzle is presented as a directed graph G(V, E) with each edge e(a, b) labeled by a boolean operator op (one of AND, OR, XOR) and an integer c (0 ≤ c ≤ 1). One Katu is solvable if one can find each