zoukankan      html  css  js  c++  java
  • POJ 3678 Katu Puzzle

    Description

    给出一个关系,包括 And,Xor,Or 问是否存在解.

    Sol

    经典的2-SAT问题.

    把每个值看成两个点,一个点代表选 (0) ,另一个代表选 (1) .

    首先来看 Xor :

    如果两个值异或起来为 (1) :那么连边 ((i_0,j_1),(i_1,j_0),(j_0,i_1),(j_1,i_0)) .

    否则 连边 ((i_0,j_0),(i_1,j_1),(j_0,i_0),(j_1,i_1)) .

    然后是 And.

    如果两个值 And 起来为 (1) :连边 ((i_0,i_1),(j_0,j_1))

    否则 连边 ((i_1,j_0),(j_1,i_0))

    最后是 Or.

    如果两个值 Or 起来为 (1) :连边 ((i_0,j_1),(j_1,i_0))

    否则 连边 ((i_1,i_0),(j_1,j_0)) .

    Tarjan 缩一下环判断一下两个点是否在一个环中就可以了.

    Code

    #include <cstdio>
    #include <iostream>
    #include <vector>
    using namespace std;
    
    const int N = 2005;
    
    int n,m,cnt,cntb;
    vector< int > g[N];
    int d[N],b[N],ins[N];
    int stk[N],top;
    
    inline int in(int x=0,char ch=getchar()){ while(ch>'9' || ch<'0') ch=getchar();
    	while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();return x; } 
    void Add_Edge(int fr,int to) { g[fr].push_back(to); }
    void Tarjan(int u,int fa) {
    	int dfsn=++cnt;d[u]=cnt,ins[u]=1,stk[++top]=u;
    	for(int i=0,v;i<(int)g[u].size();i++) {
    		v=g[u][i];
    		if(!d[v]) Tarjan(v,u);
    		if(ins[v]) d[u]=min(d[u],d[v]);
    	}if(dfsn==d[u]) {
    		for(++cntb;stk[top]!=u;top--) {
    			b[stk[top]]=cntb,ins[stk[top]]=0;
    		}ins[stk[top]]=0,b[stk[top--]]=cntb;
    	}
    //	cout<<u<<":"<<dfsn<<" "<<d[u]<<endl;
    }
    int main() {
    //	freopen("in.in","r",stdin);
    	n=in(),m=in();
    	char opt[50];
    	for(int i=1;i<=m;i++) {
    		int u=in(),v=in(),w=in();
    		scanf("%s",opt);
    		if(u>v) swap(u,v);
    		if(opt[0]=='X') {
    			if(w) {
    				Add_Edge(u*2,v*2+1);
    				Add_Edge(u*2+1,v*2);
    				Add_Edge(v*2,u*2+1);
    				Add_Edge(v*2+1,u*2);
    			}else {
    				Add_Edge(u*2,v*2);
    				Add_Edge(v*2,u*2);
    				Add_Edge(u*2+1,v*2+1);
    				Add_Edge(v*2+1,u*2+1);
    			}
    		}else if(opt[0]=='A') {
    			if(w) {
    				Add_Edge(u*2,u*2+1);
    				Add_Edge(v*2,v*2+1);
    			}else {
    				Add_Edge(u*2+1,v*2);
    				Add_Edge(v*2+1,u*2);
    			}
    		}else {
    			if(w) {
    				Add_Edge(u*2,v*2+1);
    				Add_Edge(v*2,u*2+1);
    			}else {
    				Add_Edge(u*2+1,u*2);
    				Add_Edge(v*2+1,v*2);
    			}
    		}
    	}
    	for(int i=0;i<2*n;i++) if(!d[i]) Tarjan(i,i);
    //	for(int i=0;i<2*n;i++) cout<<b[i]<<" ";cout<<endl;
    	for(int i=0;i<2*n;i++) if(b[i]==b[i^1]) return puts("NO"),0;
    	return puts("YES"),0;
    }
    

      

  • 相关阅读:
    团队展示
    平衡二叉树AVLTree
    红黑树原理
    日本楼市崩盘始末
    池化
    Spring配置多数据源
    关于C语言指针几个容易混淆的概念
    .net core 部署 Docker 所遇到的几个问题
    自定义类加载器也是无法实现加载java.lang.String的
    jquery轻量级数字动画插件jquery.countup.js
  • 原文地址:https://www.cnblogs.com/beiyuoi/p/6180480.html
Copyright © 2011-2022 走看看