CodeForces 228E The Road to Berland is Paved With Good Intentions 2Sat求解

//CodeForces 228E The Road to Berland is Paved With Good Intentions 2Sat求解
/*
题目地址:
http://codeforces.com/problemset/problem/228/E

题意:
一幅图,100个点,最多10000条边,边权为0或1,
每次可以选择一个点,将与之相连的边取反(0变为1,1变为0)
问最后能不能将所有边变为1,若能,输出索取的点,否则,输出Impossible

思路:
2Sat
设	i为选这个点,i'为不选这个点
	j为选这个点,j'为不选这个点
枚举每一条边,
如果是0:	i->j'
			i'->j
			j->i'
			j'->i

如果是1:	i->j
			i'->j'
			j->i
			j'->i'

*/



#include<stdio.h>
#include<iostream>
#include<queue>
#include<string>
using namespace std;

#define N 205
#define M 40005

int stack[N], LOW[N], DFN[N], belong[N],head[N];
int top, cnt, tot, Index, num;
bool inStack[N];

int head1[N],degree[N],order[N],color[N],id[N],re[N];
int num1,nnum;

int n,m;

struct node{
	int from;
	int to;
	int val;
}s[M];

struct Edge{
	int from;
	int to;
	int next;
}edge[M],road[M];

void addedge(int from, int to){
	edge[num].from = from;
	edge[num].to = to;
	edge[num].next = head[from];
	head[from] = num++;
}

void Tarjan(int u) { 
	int v;
	stack[++top] = u;
	inStack[u] = true;
	LOW[u] = DFN[u] = ++Index;
				
	for(int i = head[u]; i != -1; i = edge[i].next){
		v = edge[i].to;
		if (!DFN[v]) {
			Tarjan(v);
			if (LOW[u] > LOW[v])
				LOW[u] = LOW[v];
		} 	
		else if (inStack[v] && LOW[u] > DFN[v])
			LOW[u] = DFN[v];
	}
	if (LOW[u] == DFN[u]) {	
		cnt++;	
		do {
			v = stack[top--];
			inStack[v] = false;
			belong[v] = cnt;
			id[v] = cnt;
		} while (v != u);
	}
}

void init(){
	memset(head,-1,sizeof(head));
	memset(head1,-1,sizeof(head1));
	memset(DFN,0,sizeof(DFN));
	memset(inStack,0,sizeof(inStack));
	cnt = Index = top = num = num1 = 0;
}

void addroad(int from,int to){
	road[num1].from = from;
	road[num1].to=to;
	road[num1].next=head1[from];
	head1[from]=num1++;
}

void ReBuild(){
	int i,k1,k2;
	memset(degree,0,sizeof(degree));
	for(i = 0; i < num; i++){
		k1 = belong[edge[i].from];
		k2 = belong[edge[i].to];
		if(k1 != k2){
			addroad(k2,k1);
			degree[k1]++;
		}
	}
}

void TopSort(){
	nnum = 0;
	queue<int>Q;
	for(int i = 1; i <= cnt; i++)
		if(degree[i] == 0)
			Q.push(i);
		while(!Q.empty()){
			int p=Q.front();
			Q.pop();
			order[nnum++] = p;
			for(int h = head1[p]; h != -1; h = road[h].next){
				degree[road[h].to]--;
				if(degree[road[h].to] == 0)
					Q.push(road[h].to);
			}
		}
}

void dfs_color(int v){
	color[v]=-1;
	for(int h = head1[v]; h != -1;h = road[h].next)
		if(color[road[h].to] == 0)
			dfs_color(road[h].to);
}

void dfs(){
	int u,v,i,j;
	memset(color,0,sizeof(color));
	for(j = 0; j < nnum;j++){
		u = order[j];
		if(color[u] != 0)
			continue;
		color[u] = 1;
		for(i = 1; i <= 2 * n; i++){
			if(id[i]==u)
            {	
				if(i > n)
					v = i - n;
				else
					v = i + n;
				v = id[v];
				dfs_color(v);
			}
		}
	}
	memset(re,0,sizeof(re));
	for(i = 1;i <= 2 * n; i++)
		if(color[belong[i]]==1)
			re[i]=1;
}

void solve(){
	ReBuild();
	TopSort();
	dfs();
}

int main(){
	int i;
	int a,b,c;
	while(scanf("%d %d",&n,&m)!=EOF){
		init();
		for(i = 1; i <= m; ++i){
			scanf("%d %d %d",&a,&b,&c);
			s[i].from = a;
			s[i].to = b;
			s[i].val = c;
			if(c == 0){
				addedge(a,b+n);
				addedge(a+n,b);
				addedge(b,a+n);
				addedge(b+n,a);
			}
			else{
				addedge(a,b);
				addedge(a+n,b+n);
				addedge(b,a);
				addedge(b+n,a+n);
			}
		}
		for(i = 1; i <= 2 * n; i++)
			if (!DFN[i])
				Tarjan(i);
		
		for(i = 1; i <= n; i++)
			if(belong[i]==belong[i+n])
				break;

		if(i <= n)
			puts("Impossible");
		else{
			solve();
			queue<int>Q;
			for(i = 1; i <= n; ++i)
				if(re[i])
					Q.push(i);
			printf("%d\n",Q.size());
			while(!Q.empty()){
				if(Q.size() > 1)
					printf("%d ",Q.front());
				else
					printf("%d\n",Q.front());
				Q.pop();
			}
		}
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值