poj 3648

2sat,注意题意。

代码:

#include<iostream>
#include<fstream>

using namespace std;

struct e{
	int data;
	e *next;
}edge[121],edge2[122];
int n,m;

int v[121],low[121],dfn[121],stack[121],scc[121],tot,index,top;

void tarjan(int s){
	int i,j,k;
	dfn[s]=low[s]=++index;
	stack[++top]=s;
	v[s]=1;
	e *p=edge[s].next;
	while(p){
		if(dfn[p->data]==0)
		{
			tarjan(p->data);
			low[s]=min(low[s],low[p->data]);
		}
		else
			if(v[p->data])
			{
				low[s]=min(low[s],dfn[p->data]);
			}
		p=p->next;
	}
	if(low[s]==dfn[s]){
		++tot;
		
		do{
			i=stack[top--];
			scc[i]=tot;
			
			v[i]=0;
		}while(i!=s);
	}
}



void solve(){
	int i,j,k;
	index=0;tot=0;top=0;
	memset(v,0,sizeof(v));
	memset(dfn,0,sizeof(dfn));
	for(i=0;i<4*n;i++)
		if(dfn[i]==0)
			tarjan(i);
}

void build(){
	int i,j,k;
	memset(edge2,0,sizeof(edge2));
	for(i=0;i<4*n;i++)
	{
		e *p=edge[i].next;
		while(p){
			if(scc[p->data]!=scc[i])
			{
				e *q=new e;
				q->data=scc[i];
				q->next=edge2[scc[p->data]].next;
				edge2[scc[p->data]].next=q;
			}
			p=p->next;
		}
	}
}

int queue[130];

void dfs(int s){
	int i,j,k;
	v[s]=1;
	e *p=edge2[s].next;
	while(p){
		if(v[p->data]==0)
			dfs(p->data);
		p=p->next;
	}
	queue[top++]=s;
}

int ant[130];

void solve1(){
	int i,j,k;
	for(i=0;i<2*n;i++)
	{
		ant[scc[i]]=scc[i+2*n];
		ant[scc[i+2*n]]=scc[i];
	}
	build();
	top=0;
	for(i=0;i<tot;i++)
		if(v[i]==0)
			dfs(i);
	memset(v,0,sizeof(v));
	for(i=top-1;i>=0;i--)
	{
		j=queue[i];
		if(v[j]==0)
		{
			v[j]=1;
			v[ant[j]]=2;
			j=ant[j];
			e *p=edge2[j].next;
			while(p){
				v[p->data]=2;
				p=p->next;
			}
		}
	}
	for(i=1;i<n;i++)
		if(v[scc[i]]==1)
			cout<<i<<"w ";
	for(i=n;i<2*n;i++)
		if(v[scc[i]]==1)
			cout<<i-n<<"h ";
	cout<<endl;
}
		
void read(){
//	ifstream cin("in.txt");
	int i,j,k,s;
	while(1){
		cin>>n>>m;
		if(n==0&&m==0) return;
		memset(edge,0,sizeof(edge));
		s=2*n;

		e *p=new e;
		p->data=0;
		p->next=edge[n].next;
		edge[n].next=p;

		e *q=new e;
		q->data=3*n;
		q->next=edge[2*n].next;
		edge[2*n].next=q;

		for(i=0;i<n;i++)
		{
			e *p=new e;
			p->data=i+s;
			p->next=edge[i+n].next;
			edge[i+n].next=p;
			
			e*q=new e;
			q->data=i;
			q->next=edge[i+n+s].next;
			edge[i+n+s].next=q;

			e*p1=new e;
			p1->data=i+n;
			p1->next=edge[i+s].next;
			edge[i+s].next=p1;

			e *q1=new e;
			q1->data=i+n+s;
			q1->next=edge[i].next;
			edge[i].next=q1;
		}
		char c1,c2;
		for(i=1;i<=m;i++)
		{
			cin>>j>>c1>>k>>c2;
			if(c1=='h') j+=n;
			if(c2=='h') k+=n;
			e *p=new e;
			p->data=k;
			p->next=edge[j+s].next;
			edge[j+s].next=p;

			e *q=new e;
			q->data=j;
			q->next=edge[k+s].next;
			edge[k+s].next=q;
		}
		solve();
		for(i=1;i<=n*2;i++)
			if(scc[i]==scc[i+s])
				break;
		if(i<=n*2)
		{
			cout<<"bad luck"<<endl;
			continue;
		}
		else
		{
			solve1();
			
		}
	}
}

int main(){
	read();
	return 0;
}

转载于:https://www.cnblogs.com/zhaozhe/archive/2011/03/19/1988937.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值