POJ-3648-Wedding(2-sat)

POJ 2-sat 六题之四

http://blog.sina.com.cn/s/blog_64675f540100k1g9.html

题目描述:

一堆夫妇去参加一对新人的婚礼。人们坐在一个很长很长的桌子的两侧(面对面)。新郎新娘在桌子头面对面座。

新娘不希望看见她对面的一排有一对夫妇坐着(夫妇需要分开两排座)。

同时,一些人之间有暧昧关系,新娘也不希望有暧昧关系的人同时坐在她对面的一排。

问你可否满足新娘的要求,可以的话,输出一种方案。

解题报告:

首先,每个人都可能坐在桌子两侧的某一侧,这样,把每个人拆成两个点。

第一个点表示桌子左侧(我自己定义的),第二个表示右侧。即i和i’

新娘我让她坐在左侧,新郎坐在右侧。

新娘编号0,加入边i’-》i,就是说如果新娘坐右侧的话,就需要坐到左侧(这样就限定了新娘坐在左侧),新郎同样处理。

夫妇一定一左侧,一右侧。

有暧昧关系的人要么同时坐在左侧(不让新娘看见),要么一个坐在左侧,一个坐在右侧。

// File Name: 3648.cpp
// Author: zlbing
// Created Time: 2013/1/31 0:06:20

#include<iostream>
#include<string>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<cstring>
#include<stack>
using namespace std;
#define MAXN 200
struct TwoSAT{
    int n;
    vector<int>G[MAXN*2];
    bool mark[MAXN*2];
    stack<int>S;
    bool dfs(int x)
    {
        if(mark[x^1])return false;
        if(mark[x])return true;
        mark[x]=true;
        S.push(x);
        for(int i=0;i<G[x].size();i++)
        {
            int v=G[x][i];
            if(!dfs(v))return false;
        }
        return true;
    }
    void init(int _n)
    {
        n=_n;
        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[x^1].push_back(y);
        G[y^1].push_back(x);
    }
*/
    void add_clause(int x,int y)
    {
        G[x].push_back(y);
    }
    bool solve()
    {
        for(int i=0;i<2*n;i=i+2)
        {
            if(!mark[i]&&!mark[i+1]){
                  while(!S.empty())
                  {
                      S.pop();
                  }
                if(!dfs(i))
                {
                    while(!S.empty())
                    {
                        mark[S.top()]=false;
                        S.pop();
                    }
                    if(!dfs(i+1))return false;
                }
            }
        }
        char e;
        bool first=true;
        for(int i=4;i<4*n;i++)
            if(mark[i]){
                int k=i/4;
                if(i%4<2)e='w';
                else e='h';
                if(i%2==0){
                    if(first){
                    printf("%d%c",k,e);
                    first=false;        
                    }else 
                    printf(" %d%c",k,e);
                }
            }
        printf("\n");
        return true;
    }
};
TwoSAT solver;
int main(){
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        solver.init(2*n);
        if(n==0&&m==0)
            break;
        int a,b;
        char cha,chb;
        solver.add_clause(1,0);
        solver.add_clause(2,3);
        for(int i=1;i<n;i++)
        {
            a=i*2,b=i*2+1;
            solver.add_clause(a*2,b*2+1);
            solver.add_clause(b*2+1,a*2);
            solver.add_clause(a*2+1,b*2);
            solver.add_clause(b*2,a*2+1);
        }
        for(int i=0;i<m;i++)
        {
            scanf("%d%c %d%c",&a,&cha,&b,&chb);
            a=cha=='w'?a*2:a*2+1;
            b=chb=='w'?b*2:b*2+1;
            solver.add_clause(a*2+1,b*2);
            solver.add_clause(b*2+1,a*2);
        }
        if(!solver.solve())
            printf("bad luck\n");
    }
    return 0;
}

 

posted @ 2013-01-31 01:05  z.arbitrary  阅读(264)  评论(0编辑  收藏  举报