UVA11294

前言

一眼题

思路

首先我们可以得到每一个人不是在左边就是在右边,那么对于每个人只有两种选择,符合 2-SAT 的标准,然后就可以思考如何连边了。

  • 如果两个人是夫妻关系,那么他们不能做到同一边,所以如果 \(x_i\) 坐右边 \(y_i\) 坐左边,如果 \(x_i\) 坐左边 \(y_i\) 做右边,然后以此类推。
  • 如果两个人是通奸关系那么他们不能都坐到新郎那边,所以如果 \(x_i\) 坐新郎那边则 \(y_i\) 做新娘那边,然后以此类推。

这里处理时有一个小技巧,可以先将新郎和新娘的位置确定在左边还是右边以便于后面的输出方案。

这里我将 \(1\sim n\) 表示为第 \(i\) 组的妻子,\(n+1\sim 2\times n\) 表示第 \(i\) 组的丈夫,然后 \(1\sim 2\times n\) 表示在新娘那一边 \(2\times n+1\sim 4\times n\) 表示在新郎那一边。

代码

#include <bits/stdc++.h>
using namespace std ;
#define int long long
#define rep(i,x,y) for(int i=x;i<=y;i++)
#define rep1(i,x,y) for(int i=x;i>=y;i--)
#define fire signed
#define kong putchar(' ')
#define end putchar('\n')
#define in(x) scanf("%lld",&x)
#define lcm(x,y) x*y/__gcd(x,y)
#define pb push_back
#define il inline
il void print(int x) {
	if(x>=10) print(x/10);
	putchar(x%10+'0');
}
int n,m;
const int N=1000;
vector<int>v[N];
int dfn[N],low[N],is[N];
int cnt,val[N],idx;
stack<int>s;
void tarjan(int x) {
	dfn[x]=low[x]=++idx;
	s.push(x);
	is[x]=1;
	for(auto to:v[x]) {
		if(!dfn[to]) tarjan(to),low[x]=min(low[x],low[to]);
		else if(is[to]) low[x]=min(low[x],dfn[to]);
	} 
	if(low[x]==dfn[x]) {
		int p;
		cnt++;
		do{
			p=s.top();
			s.pop();
			is[p]=false;
			val[p]=cnt;
		}while(p!=x);
	} 
}
/*
1~n 女(
1+n~2*n 男 
*/
int get(int x,char c) {
	return c=='w'?x+1:x+1+n;
}
int p(int x) {
	return x+2*n;
}
fire main() {
	while(cin>>n>>m,n) {
		memset(dfn,0,sizeof dfn);
		memset(low,0,sizeof low);
		memset(is,0,sizeof is);
		memset(val,0,sizeof val);
		rep(i,1,n*4) v[i].clear();
		v[1+2*n].push_back(1);
		v[1+n].push_back(1+n+2*n);
		rep(i,1,m) {
			char a,b;
			int A,B;
			cin>>A>>a>>B>>b;
			int now=get(A,a),now1=get(B,b);
			v[p(now1)].push_back(now);
			v[p(now)].push_back(now1);
//			cout<<now<<" "<<now1<<endl;
		}
		rep(i,2,n) v[i].push_back(i+n+2*n),v[i+n].push_back(p(i)),v[p(i)].push_back(i+n),v[p(i+n)].push_back(i);
		rep(i,1,4*n) if(!dfn[i]) tarjan(i);
		int f=false;
		rep(i,1,2*n) {
			if(val[i]==val[p(i)]) {
				puts("bad luck");
				f=1;
				break;
			}
		}
		if(f) continue;
		vector<int>ans;
		rep(i,2,n) if(val[i]<val[p(i)]) ans.push_back(i);
		rep(i,n+2,2*n) if(val[i]<val[p(i)]) ans.push_back(i);
		for(auto x:ans) {
			if(x>n) cout<<x-n-1<<'h'<<' ';
			else cout<<x-1<<'w'<<' '; 
		}
		cout<<endl;
	}
	return false;
}
/*
10 6
3h 7h
5w 3w
7h 6w
8w 3w
7h 3w
2w 5h
0 0
*/
posted @ 2024-01-31 11:57  highkj  阅读(9)  评论(0)    收藏  举报