• Katu Puzzle


    POJ

    题意:有(N)个变量(x_1-x_n),每个变量的可能取值是0或1.给定(M)个算式,每个算式形如(X_a) (op) (X_b=c),其中(a,b)是两个变量的编号,(c)是数字0或1,(op)(and),(or),(xor)三个位运算之一.求是否存在对每个变量的合法赋值,使得所有算式都成立.(n<=1000,m<=10^6.)

    分析:(2-SAT)问题,先要转换成(2-SAT)的形式.设节点(a)表示(x_a)赋值为0,节点(a+n)表示(x_a)赋值为1:

    (a) (and) (b=0),则(x_a=1)时,(x_b)必须(=0),连有向边((a+n,b)) .其它情况都这样去想就好.注意:能够连边要满足的条件是:"若p,则必须q".

    建图后,跑有向图(Tarjan),如果有一个节点(i),(i)(i+n)都属于同一个强连通分量,则不存在合法赋值了.

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<set>
    #define ll long long
    using namespace std;
    inline int read(){
        int x=0,o=1;char ch=getchar();
        while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
        if(ch=='-')o=-1,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*o;
    }
    const int N=1005;
    const int M=4e6+5;
    int tot,head[N],nxt[M],to[M];
    int tim,top,num,dfn[N],low[N],st[M],color[N];
    inline void add(int a,int b){nxt[++tot]=head[a];head[a]=tot;to[tot]=b;}
    inline void tarjan(int u){
    	dfn[u]=low[u]=++tim;st[++top]=u;
    	for(int i=head[u];i;i=nxt[i]){
    		int v=to[i];
    		if(!dfn[v]){
    			tarjan(v);
    			low[u]=min(low[u],low[v]);
    		}
    		else if(!color[v])low[u]=min(low[u],dfn[v]);
    	}
    	if(dfn[u]==low[u]){
    		color[u]=++num;
    		while(st[top]!=u){
    			color[st[top]]=num;
    			--top;
    		}
    		--top;
    	}
    }
    int main(){
    	int n=read(),m=read();
    	for(int i=1;i<=m;++i){
    		int a=read(),b=read(),c=read();
    		++a;++b;string s;cin>>s;
    		if(s[0]=='A'){
    			if(c==0)add(a+n,b),add(b+n,a);
    			else add(a,a+n),add(b,b+n);
    		}
    		else if(s[0]=='O'){
    			if(c==0)add(a+n,a),add(b+n,b);
    			else add(a,b+n),add(b,a+n);
    		}
    		else if(s[0]=='X'){
    			if(c==0){
    				add(a,b);add(b,a);
    				add(a+n,b+n);add(b+n,a+n);
    			}
    			else{
    				add(a,b+n);add(b,a+n);
    				add(a+n,b);add(b+n,a);
    			}
    		}
    	}
    	for(int i=1;i<=n*2;++i)if(!dfn[i])tarjan(i);
    	for(int i=1;i<=n;++i)
    		if(color[i]==color[i+n]){
    			puts("NO");return 0;
    		}
    	puts("YES");
        return 0;
    }
    
    
  • 相关阅读:
    指针
    基本数据类型和string类型的转换
    golang的数据类型之基本数据类型的默认值和转换
    golang的数据类型之字符串类型
    golang的数据类型之布尔类型
    windows pyspider WEB显示框太小解决方法
    MYSQL的全局变量和会话变量
    php 日期计算 总结
    使用 PHPMailer 发送邮件
    MySQL两种表存储结构MyISAM和InnoDB的性能比较测试
  • 原文地址:https://www.cnblogs.com/PPXppx/p/11592627.html
Copyright © 2020-2023  润新知