POJ 3648 Wedding (2-SAT 输出路径)

题意:

有一对新人要结婚了,所以他们邀请了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("");
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值