zoukankan      html  css  js  c++  java
  • P5782-[POI2001]和平委员会【2-SAT】

    正题

    题目链接:https://www.luogu.com.cn/problem/P5782


    题目大意

    (n)对人,每对之间恰好有一个人出席。(m)对仇恨关系表示两个人不能同时出席。

    求是否有解并输出。

    (1leq nleq 8000,1leq mleq 20000)


    解题思路

    裸的( ext{2-SAT})。AJ的任务罢了。

    时间复杂度(O(n))


    code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<stack>
    using namespace std;
    const int N=3e5+10;
    struct node{
    	int to,next;
    }a[N<<2];
    int n,m,tot,cnt,num,ls[N],dfn[N],low[N],col[N];
    bool ins[N];stack<int> s;
    void addl(int x,int y){
    	a[++tot].to=y;
    	a[tot].next=ls[x];
    	ls[x]=tot;return;
    }
    void tarjan(int x){
    	dfn[x]=low[x]=++cnt;
    	s.push(x);ins[x]=1;
    	for(int i=ls[x];i;i=a[i].next){
    		int y=a[i].to;
    		if(!dfn[y]){
    			tarjan(y);
    			low[x]=min(low[x],low[y]);
    		}
    		else if(ins[y])
    			low[x]=min(low[x],dfn[y]);
    	}
    	if(dfn[x]==low[x]){
    		++num;
    		while(s.top()!=x){
    			ins[s.top()]=0;
    			col[s.top()]=num;
    			s.pop();
    		}
    		col[x]=num;ins[x]=0;
    		s.pop();
    	}
    	return;
    }
    int main()
    {
    	scanf("%d%d",&n,&m);n*=2;
    	for(int i=1;i<=n;i+=2)
    		addl(i+n,i+1),addl(i+1+n,i),addl(i+1,i+n),addl(i,i+1+n);
    	for(int i=1;i<=m;i++){
    		int x,y;
    		scanf("%d%d",&x,&y);
    		addl(x,y+n);addl(y,x+n);
    	}
    	for(int i=1;i<=2*n;i++)
    		if(!dfn[i])tarjan(i);
    	for(int i=1;i<=n;i++)
    		if(col[i]==col[i+n])
    			return puts("NIE")&0;
    	for(int i=1;i<=n;i++)
    		if(col[i]<col[i+n])printf("%d
    ",i);
    	return 0;
    }
    
  • 相关阅读:
    更改Ubuntu默认python版本的方法
    hdu 5656 CA Loves GCD(dp)
    hdu 5655 CA Loves Stick
    hdu 5650 so easy (异或)
    2016.3.28
    Android 之 ExpandableListView 的使用
    Android之字符串的拆分-split
    Android之SAX解析XML
    hdu 5642 King's Order(数位dp)
    hdu 5641 King's Phone(暴力模拟题)
  • 原文地址:https://www.cnblogs.com/QuantAsk/p/14728321.html
Copyright © 2011-2022 走看看