zoukankan      html  css  js  c++  java
  • poj3678-Katu Puzzle

    (n)个bool变量和(m)条限制,每条限制为a op b=c的形式,其中op为逻辑运算,问是否存在合法解。

    分析

    这一类问题叫做2-SAT问题,有很多个两种取值的变量,其中有一些限制条件。2-SAT问题我们采用建模的方式,如果(a)选就一定要选(b),那么连有向边((a,b))。2-SAT问题有解的条件就是(a)(!a)不在同一个强连通分量中,也就是说不产生矛盾。

    几个基本逻辑运算的连边如下,其他的都可以转化为这几种:

    • a=true,(!a o a)
    • a=false,(a o !a)
    • a or b=true,(!a o b,!b o a)
    • a or b=false,等价于(a=false,b=false)
    • a and b=true,等价于(a=true,b=true)
    • a and b=false,(a o !b,b o !a)
    • a xor b=true,(a o !b,!a o b,b o !a,!b o a)
    • a xor b=false,(a o b,!a o !b,b o a,!b o !a)
    • a=b,等价于a xor b=false
    • (a e b),等价于a xor b=true

    这道题就这样做完啦。

    代码

    #include<cstdio>
    #include<cctype>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int read() {
    	int x=0,f=1;
    	char c=getchar();
    	for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
    	for (;isdigit(c);c=getchar()) x=x*10+c-'0';
    	return x*f;
    }
    const int maxn=2e3+10;
    const int maxm=4e6+10;
    int dfn[maxn],low[maxn],dft=0,id[maxn],sta[maxn],top=0,col=0;
    bool ins[maxn];
    struct edge {
    	int v,nxt;
    };
    struct graph {
    	edge e[maxm];
    	int h[maxn],tot;
    	graph ():tot(0) {}
    	void add(int u,int v) {
    		e[++tot]=(edge){v,h[u]};
    		h[u]=tot;
    	}
    	void Tarjan(int x) {
    		dfn[x]=low[x]=++dft;
    		sta[++top]=x;
    		ins[x]=true;
    		for (int i=h[x],v=e[i].v;i;i=e[i].nxt,v=e[i].v) if (!dfn[v]) {
    			Tarjan(v);
    			low[x]=min(low[x],low[v]);
    		} else if (ins[v]) low[x]=min(low[x],dfn[v]);
    		if (low[x]==dfn[x]) {
    			++col;
    			do id[sta[top--]]=col; while (sta[top+1]!=x);
    		}
    		ins[x]=false;
    	}
    	bool run(int n) {
    		for (int i=1;i<=n;++i) if (id[i]==id[n+i]) return false;
    		return true;
    	}
    } A;
    int main() {
    #ifndef ONLINE_JUDGE
    	freopen("test.in","r",stdin);
    #endif
    	int n=read(),m=read();
    	for (int i=1;i<=m;++i) {
    		int x=read()+1,y=read()+1,z=read();
    		static char op[8];
    		scanf("%s",op);
    		if (op[0]=='A' && z) A.add(x+n,x),A.add(y+n,y); else
    		if (op[0]=='A' && !z) A.add(x,y+n),A.add(y,x+n); else
    		if (op[0]=='O' && z) A.add(x+n,y),A.add(y+n,x); else
    		if (op[0]=='O' && !z) A.add(x,x+n),A.add(y,y+n); else 
    		if (op[0]=='X' && z) A.add(x,y+n),A.add(x+n,y),A.add(y,x+n),A.add(y+n,x); else 
    		if (op[0]=='X' && !z) A.add(x,y),A.add(x+n,y+n),A.add(y,x),A.add(y+n,x+n);
    	}
    	for (int i=1;i<=(n<<1);++i) if (!id[i]) A.Tarjan(i);
    	puts(A.run(n)?"YES":"NO");
    	return 0;
    }
    
  • 相关阅读:
    在windows系统下,配置vue项目一键启动文件
    CSS中设置元素的圆角矩形
    CSS中使用文本阴影与元素阴影
    如何使用CSS3中的结构伪类选择器和伪元素选择器
    CSS中的z-index属性如何使用
    深入学习CSS中如何使用定位
    css中如何使用border属性与display属性
    深入了解CSS中盒子模型
    CSS中如果实现元素浮动和清除浮动,看这篇文章就足够了
    CSS标准文档流
  • 原文地址:https://www.cnblogs.com/owenyu/p/6741731.html
Copyright © 2011-2022 走看看