luogu P5782 [POI2001]和平委员会 |2-sat

题目描述

根据宪法,Byteland 民主共和国的公众和平委员会应该在国会中通过立法程序来创立。 不幸的是,由于某些党派代表之间的不和睦而使得这件事存在障碍。 此委员会必须满足下列条件:

每个党派都在委员会中恰有 11 个代表。
如果 22 个代表彼此厌恶,则他们不能都属于委员会。
每个党在议会中有 22 个代表。代表从 11 编号到 2n2n。 编号为 2i-12i−1 和 2i2i 的代表属于第 ii 个党派。

任务:写一程序读入党派的数量和关系不友好的代表对,计算决定建立和平委员会是否可能,若行,则列出委员会的成员表。

输入格式

第一行有两个非负整数 n,mn,m。他们各自表示:党派的数量 nn 和不友好的代表对 mm。

接下来 mm 行,每行为一对整数 a,ba,b,表示代表 aa , bb 互相厌恶。

输出格式

如果不能创立委员会,则输出信息 NIE。

若能够成立,则输出包括 nn 个从区间 11 到 2n2n 选出的整数,按升序写出,每行一个,这些数字为委员会中代表的编号。

Special Judge :如果委员会能以多种方法形成,程序可以只输出它们的某一个。


#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=5e4+10,M=1e5+10;
int nxt[M],head[N],go[M],tot;
inline void add(int u,int v){
	nxt[++tot]=head[u]; head[u]=tot; go[tot]=v;
}
int dfn[N],low[N],st[N],co[N],num,top,col;
inline void Tarjan(int u,int f){
	dfn[u]=low[u]=++num;
	st[++top]=u;
	for(int i=head[u];i;i=nxt[i]){
		int v=go[i];
		if(!dfn[v]){
			Tarjan(v,u);
			low[u]=min(low[u],low[v]);
		}else if(!co[v]){
			low[u]=min(low[u],dfn[v]);
		}
	}
	if(dfn[u]==low[u]){
		co[u]=++col;
		while(st[top]!=u){
			co[st[top]]=col;
			--top;
		}
		--top;
	}
}
int n,m;
inline int par(int x){
	return (x%2==0)?x-1:x+1;
}
signed main(){
	cin>>n>>m;
	for(int i=1,x,y;i<=m;i++){
		scanf("%d%d",&x,&y);
		add(x,par(y));
		add(y,par(x));
	}
	for(int i=1;i<=2*n;i++)
	if(!dfn[i])Tarjan(i,-1);
	
	for(int i=1;i<=2*n;i+=2)
	if(co[i]==co[i+1]){
		cout<<"NIE"<<endl;
		return 0;
	}
    for(int i=1;i<=2*n;i+=2)
    if(co[i]<co[i+1])cout<<i<<endl;
    else cout<<i+1<<endl;
}
原文地址:https://www.cnblogs.com/naruto-mzx/p/12093887.html