题意:
有一对新人要结婚了,所以他们邀请了n对夫妻来参加婚礼。
然后就是喜闻乐见的吃饭情节了,然而在坐座位的时候有要求,桌子有两边,这夫妻不能在同一边。这是最初的条件,然后就是。。。有m对通奸关系。。。哇这样这的好吗,我还是个孩子5555~有通奸关系的不能在一边(注意这里的通奸关系是任意的,可以男男女女男女,新郎新娘也可以。。。)
(我tm读完题就知道出题人脑子不正常了。。。)
然后呢,新娘由于穿着华丽的婚纱,所以她看不见自己边的人(???),然后最后一个约束来了:新娘不想看见通奸的人在新娘对面,要你输出一个合法的坐在新娘边的结果。
坑点:
总的来说这道题很迷。。
1. 读取的时候不要加空格。。会re。。1w2h这种也是合法输入
2. 新娘由于看不见自己边的人,所以任意和新娘通奸的都不会构成矛盾,但新浪的关系需要处理。
3. 跑2-sat时,我们得到的一定是无矛盾的一边的解。所以我们将h和w调换一下就好
总结:
这题面有毒。。
1. 2-sat反向建边后不需要传递不选关系,因为如果当前节点入度为0了,那么对应的节点一定出度为0或后续节点已被访问(因为我们构造的是一个对称的图形,包括缩点后的新图,所以当前节点的入度为0时,代表着我这个节点的前驱节点已经访问完了,由此得到对应节点的后续节点已经访问完了。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string.h>
#include <queue>
#include <cmath>
#define pi acos(-1.0)
#define eps 1e-6
typedef long long int lli;
using namespace std;
const int maxn = 2200;
struct edge{
int from,to,v,next;
}ed[400000];
int head[maxn];
int cnte;
void ae(int x,int y){
ed[++cnte].to = y;
ed[cnte].next = head[x];
head[x]=cnte;
}
int ma[2200][2200];//新图
int col[2200];
int fanxiang[2200];//由新点找旧点
int dfn[maxn],low[maxn],vis[maxn],stak[maxn],belong[maxn],cntc,cnts,index;//strong connected component //cnt of stack
void dfs(int u){
dfn[u]=low[u] = ++index;
stak[cnts++]=u;
vis[u]=1;
for(int i = head[u];i!=-1;i=ed[i].next){
int v = ed[i].to;
if(!dfn[v]){
dfs(v);
low[u] = min(low[u],low[v]);
}
else if(vis[v]){
low[u] = min(low[u],dfn[v]);
}
}
if(dfn[u]==low[u]){
cntc++;int v;
do{
v = stak[--cnts];
vis[v] = 0;
belong[v] = cntc;
fanxiang[cntc] = v;
}while(v!=u);
}
}
int n,m;
void tarjan(){
for(int i = 1;i <= 2*n;i++){
if(!dfn[i]){
dfs(i);
}
}
}
int in[maxn];
int main(){
int t,a,b;char c,d;
while(~scanf("%d%d",&n,&m),n||m){
memset(head,-1,sizeof(head));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(in,0,sizeof(in));
memset(col,0,sizeof(col));
memset(ma,0,sizeof(ma));
memset(vis,0,sizeof(vis));
cnte=cntc=index=0;
for(int i = 1;i <= m;i++){
scanf("%d%c%d%c",&a,&c,&b,&d);
a++;b++;
if(c == 'w'){
if(a == 1) continue;
if(d == 'w'){
if(b == 1) continue;
ae(a,b+n);ae(b,a+n);
}
else{
ae(a,b);ae(b+n,a+n);
}
}
else{
if(d == 'w'){
if(b == 1) continue;
ae(a+n,b+n);ae(b,a);
}
else{
ae(a+n,b);ae(b+n,a);
}
}
}
ae(1,1+n);
tarjan();
int flag = 1;
for(int i = 1;i <= n;i++){
if(belong[i] == belong[i+n]){
flag = 0;break;
}
}
if(flag == 0){
puts("bad luck");
}
else{
queue<int> q;
for(int i = 1;i <= 2*n;i++){
for(int j = head[i];j!=-1;j=ed[j].next){
int to = ed[j].to,ii = belong[i],jj = belong[to];
if(ii != jj && ma[jj][ii]==0){
ma[jj][ii] = 1;in[ii]++;
}
}
}
for(int i = 1;i <= cntc;i++){
if(in[i] == 0) q.push(i);
}
int top;
while(!q.empty()){
top = q.front();
q.pop();
for(int i = 1;i <= cntc;i++){
if(ma[top][i] == 1){
in[i]--;
if(in[i] == 0)
q.push(i);
}
}
if(col[top] == 0){
col[top] = 1;
int to = fanxiang[top];
if(to > n) to -= n;
else to += n;
to = belong[to];
col[to] = -1;
//dfscol(to);
}
}
int first = 0;
for(int i = 2;i <= n;i++){
if(col[belong[i]] == -1){
if(!first){
first = 1;
}
else
printf(" ");
printf("%dw",i-1);
}
else{
if(!first){
first = 1;
}
else
printf(" ");
printf("%dh",i-1);
}
}
puts("");
}
}
}