zoukankan      html  css  js  c++  java
  • UOJ210寻找罪犯

    UOJ210

    (2-sat)问题

    这算前后缀优化嘛(?)感觉不算啊

    设置(2*n)个节点表示某个人是不是劫匪

    再设置(2*m)个节点表示第(i)句话以及之前有没有说过谎

    具体连边在注释里说叭

    #include<bits/stdc++.h>
    using namespace std;
    namespace red{
    #define ls(p) (p<<1)
    #define rs(p) (p<<1|1)
    #define mid ((l+r)>>1)
    #define y1 qwq 
    	inline int read()
    	{
    		int x=0;char ch,f=1;
    		for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
    		if(ch=='-') f=0,ch=getchar();
    		while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    		return f?x:-x;
    	}
    	const int N=3e6+10,inf=1<<30;
    	int n,m,num;
    	int pre[N],ans[N];
    	int head[N],cnt;
    	struct point
    	{
    		int nxt,to;
    		point(){}
    		point(const int &nxt,const int &to):nxt(nxt),to(to){}
    	}a[N<<1];
    	inline void link(int x,int y)
    	{
    		a[++cnt]=(point){head[x],y};head[x]=cnt;
    	}
    	inline int check(int a,int b){return a+b*n;}
    	inline int work(int a,int b){return (n<<1)+a+b*m;}
    	int dfn[N],low[N],st[N],col[N];
    	int idx,top,sum;
    	inline void tarjan(int now)
    	{
    		dfn[now]=low[now]=++idx;
    		st[++top]=now;
    		for(int i=head[now];i;i=a[i].nxt)
    		{
    			int t=a[i].to;
    			if(!dfn[t])
    			{
    				tarjan(t);
    				low[now]=min(low[now],low[t]);
    			}
    			else if(!col[t]) low[now]=min(low[now],dfn[t]);
    		}
    		if(dfn[now]==low[now])
    		{
    			col[now]=++sum;
    			while(st[top]!=now) col[st[top--]]=sum;
    			--top;
    		}
    	}
    	inline void main()
    	{
    		n=read(),m=read();
    		for(int i=1;i<=n;++i) pre[i]=2*m+1;
    		for(int x,y,opt,i=1;i<=m;++i)
    		{
    			x=read(),y=read(),opt=read()^1;
    			link(check(y,opt^1),work(pre[x],0));
    			//这句话是假话,以前都是真话 
    			link(work(pre[x],1),check(y,opt));
    			//上句话是假话,这句话是真话 
    			link(work(i,0),check(y,opt));
    			//这句话以及之前都是真话 
    			link(check(y,opt^1),work(i,1));
    			//这句话是假话,这句话以及以前有假话 
    			link(work(i,0),work(pre[x],0));
    			//这句话以及以前都是真话,这句话以前都是真话 
    			link(work(pre[x],1),work(i,1));
    			// 这句话以前有假话,这句话以及以前有假话 
    			pre[x]=i;
    		}
    		for(int i=1;i<=n;++i)
    		{
    			link(work(pre[i],1),check(i,1));
    			//这个人说过假话,这个人死啦死啦滴 
    			link(check(i,0),work(pre[i],0));
    			//这个人很诚实,是个好人 
    		}
    		for(int i=1;i<=(n+m)<<1;++i)
    			if(!dfn[i]) tarjan(i);
    		for(int i=1;i<=n;++i)
    		{
    			if(col[i]==col[i+n])
    			{
    				puts("Impossible");
    				return;
    			}
    			else if(col[i]>col[i+n]) ans[++num]=i;
    		}
    		printf("%d
    ",num);
    		for(int i=1;i<=num;++i) printf("%d ",ans[i]);
    	}
    }
    signed main()
    {
    	//freopen("haha.in","r",stdin);
    	red::main();
    	return 0;
    }
    
  • 相关阅读:
    sql删除注意的问题
    lua创建文件
    linux部分常用命令
    已知账户和密码进行远程桌面
    excel2013超链接进不去,提示“您的组织策略不允许...”
    2019-2020-1 20199321《Linux内核原理与分析》第七周作业
    《深入理解计算机系统》第一章读书笔记 20199321
    《文献管理与信息分析》速读笔记
    《深入理解计算机系统》速读笔记
    《构建之法现代软件工程》速读笔记
  • 原文地址:https://www.cnblogs.com/knife-rose/p/12700973.html
Copyright © 2011-2022 走看看