Uva 11294 Wedding(2-SAT)

49 篇文章 0 订阅
4 篇文章 0 订阅

题意:有n对夫妻参加婚宴,所有人坐在餐桌的左侧或右侧,一对夫妻不能坐在同侧,m对吵架的人也不能同时坐在新娘的对侧,求方案。


分析:mark[i] = 1表示i号丈夫和新娘同桌,然后建图。

#include<iostream>
#include<string>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<cstring>
#include<stack>
#include<cmath>
#include<queue>
#define INF 0x3f3f3f3f
#define eps 1e-9
#define MAXN 100005
using namespace std;
int n,m;  
vector <int> G[MAXN];  
bool mark[MAXN];  
int S[MAXN],num[MAXN],age[MAXN],c;  
void init()  
{  
    for(int i = 0;i < 2*n;i++) G[i].clear();  
    memset(mark,0,sizeof(mark));  
}  
void add_clause(int x,int xval,int y,int yval)  
{  
    x = x * 2 + xval;  
    y = y * 2 + yval;  
    G[y].push_back(x^1);  
    G[x].push_back(y^1);   
}  
bool dfs(int x)  
{  
    if(mark[x^1]) return false;  
    if(mark[x]) return true;  
    mark[x] = true;  
    S[c++] = x;  
    for(int v : G[x])  
     if(!dfs(v)) return false;  
    return true;   
}  
bool jud()  
{  
    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;  
}  
int main()
{
	while(~scanf("%d%d",&n,&m) && n+m)
	{
		n--;
		init();
		for(int i = 1;i <= m;i++)
		{
			char x[10],y[10];
			scanf("%s%s",x,y);
			if(x[strlen(x)-1] == y[strlen(y)-1] && x[strlen(x)-1] == 'w')
			{
				x[strlen(x)-1] = y[strlen(y)-1] = '\0';
				int a = atoi(x)-1,b = atoi(y)-1;
				add_clause(a,0,b,0);		
			} 
			else 
			if(x[strlen(x)-1] == y[strlen(y)-1] && x[strlen(x)-1] == 'h')
			{
				x[strlen(x)-1] = y[strlen(y)-1] = '\0';
				int a = atoi(x)-1,b = atoi(y)-1;
				add_clause(a,1,b,1);	
			}
			else
			if(y[strlen(y)-1] == 'w' && x[strlen(x)-1] == 'h')
			{
				x[strlen(x)-1] = y[strlen(y)-1] = '\0';
				int a = atoi(x)-1,b = atoi(y)-1;
				if(a == b) continue;
				add_clause(a,1,b,0);	
			}
			else 
			{
				x[strlen(x)-1] = y[strlen(y)-1] = '\0';
				int a = atoi(x)-1,b = atoi(y)-1;
				if(a == b) continue;
				add_clause(a,0,b,1);
			}
		}
		if(!jud()) cout<<"bad luck"<<endl;
		else 
		{
			for(int i = 0;i < n;i++)
			{
				if(mark[2*i+1]) cout<<i+1<<"w";
				 else cout<<i+1<<"h";
				if(i != n - 1) cout<<" ";
			}
			cout<<endl;
		}
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值