您的位置:首页 > 其它

[POI 2001][cogs 313]和平委员会

2015-08-11 17:16 323 查看

[POI2001] 和平委员会

★★ 输入文件:
spo.in
输出文件:
spo.out
评测插件

时间限制:1 s 内存限制:128 MB

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

此委员会必须满足下列条件:

每个党派都在委员会中恰有1个代表,
如果2个代表彼此厌恶,则他们不能都属于委员会。

每个党在议会中有2个代表。代表从1编号到2n。 编号为2i-1和2i的代表属于第I个党派。

任务

写一程序:

从文本文件读入党派的数量和关系不友好的代表对,
计算决定建立和平委员会是否可能,若行,则列出委员会的成员表,
结果写入文本文件。

输入

在文本文件的第一个行有2非负整数n和m。 他们各自表示:党派的数量n,1 < =n < =8000和不友好的代表对m,0 <=m <=20000。 在下面m行的每行为一对整数a,b,1<=a

输出

如果委员会不能创立,文本文件中应该包括单词NIE。若能够成立,文本文件SPO.OUT中应该包括n个从区间1到2n选出的整数,按升序写出,每行一个,这些数字为委员会中代表的编号。如果委员会能以多种方法形成,程序可以只写他们的某一个。

样品输入

3 2
1 3
2 4

样品输出

1
4
5


本来是要做模板题的。。不知道还有什么神解法。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
#define maxn 50010
struct TwoSAT{
	int n;
	vector<int>G[8010*2];
	bool mark[maxn];
	int S[maxn],c;
	
	void init(int n){
		this->n=n;
		for(int i=0;i<2*n;i++)G[i].clear();
		memset(mark,0,sizeof mark);
	}
	
	bool DFS(int x){
		if(mark[x^1])return false;
		if(mark[x])return true;
		mark[x]=true;S[c++]=x;
		for(int i=0;i<G[x].size();i++)
			if(!DFS(G[x][i]))return false;
		return true;
	}
	
	void add(int u,int v){
		//u=u<<1^uval;v=v<<1^vval;
		G[u].push_back(v^1);
		G[v].push_back(u^1);
	}
	
	bool solve(){
		for(int i=0;i<2*n;i+=2){
			if(!mark[i]&&!mark[i^1]){
				c=0;
				if(!DFS(i)){
					while(c>0)mark[S[--c]]=false;
					if(!DFS(i^1))return false;		
				}
			}
		}return true;
	}
}SAT;
int n,m;
int main(){
	freopen("spo.in","r",stdin);
	freopen("spo.out","w",stdout);
	scanf("%d%d",&n,&m);
	SAT.init(n);
	int u,v;
	for(int i=1;i<=m;i++){
		scanf("%d%d",&u,&v);
		u--;v--;SAT.add(u,v);
	}
	if(!SAT.solve())printf("NIE");
	else{
		for(int i=1;i<=2*n;i+=2)
			if(SAT.mark[i-1])printf("%d\n",i);
			else printf("%d\n",i+1);
	}
	return 0;	
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: