`
king_tt
  • 浏览: 2258059 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

POJ 3648 Wedding(2-SAT+输出方案)

 
阅读更多

【题目链接】

http://poj.org/problem?id=3648


【题目大意】

有n-1对夫妇被一对新郎新娘邀请来参加婚礼,他们要坐在一条长桌上,可以选择坐在左边或者右边。每对夫妻都不能坐在同一边,他们只能是面对面坐着。

但是这些人中有JQ,共有m对有JQ(新郎也可能有奸情,可怜的新娘...)。要求这些JQ对不能同时坐在新娘的对面。即,每一对JQ者,他们可以同时坐在和新娘同一边,也可以一个和新娘同一边而另一个在新娘对面即可。

要求找到一种方案并输出,如果没有方案输出bad luck


【思路】

对于每一对夫妇,有两种选择,要么女方和新娘同一边,要么男方和新娘坐在同一边。

然后是根据JQ关系加边。



【代码】

#include<iostream> 
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define WHITE -1
#define RED  1
#define BLUE 0
using namespace std;

typedef long long int64;

const int MAXN = 50;
const int VN = MAXN*2;
const int EN = VN*VN;

int n, m;

struct Edge{
    int u, v, next; 
};

struct Graph{
    int size, head[VN];
    Edge E[EN];
    void init(){size=0; memset(head, -1, sizeof(head));};
    void addEdge(int u, int v){
        E[size].u = u; E[size].v = v;
        E[size].next = head[u];
        head[u] = size++;
    }
}g, g1;

class Two_Sat{
public:
    bool check(const Graph&g, const int n){
        scc(g, 2*n);
        for(int i=0; i<n; ++i)
            if(belong[i] == belong[i+n])
                return false;
        return true;
    }
    void toposort(const Graph& g, Graph& g1, const int n){
        g1.init();
        memset(indeg, 0, sizeof(indeg));
        for(int i=0; i<n; ++i){
            opp[belong[i]] = belong[i+n];
            opp[belong[i+n]] = belong[i];
        }

        for(int e=0; e<g.size; ++e){
            int u = belong[g.E[e].u];
            int v = belong[g.E[e].v];
            if(u==v) continue;
            ++indeg[u];
            g1.addEdge(v, u);
        }

        queue<int>que;
        memset(color, WHITE, sizeof(color));
        for(int i=1; i<=bcnt; ++i)
            if(!indeg[i])
                que.push(i);

        while(!que.empty()){
            int u = que.front(); 
            que.pop();
            if(color[u] != WHITE) continue;
            color[u] = RED;
            color[opp[u]] = BLUE;

            for(int e=g1.head[u]; e!=-1; e=g1.E[e].next){
                int v = g1.E[e].v;
                if(--indeg[v] == 0){
                    que.push(v);
                }
            }
        }

        // 输出方案
        printf("1%c",color[belong[1]]==RED?'w':'h');
        for(int i=2; i<n; ++i){
            printf(" %d%c", i, color[belong[i]]==RED?'w':'h');
        }
        puts("");
    }
private:
    void tarjan(const Graph&g, const int u){
        int v;
        DFN[u] = low[u] = ++idx;
        sta[top++] = u;
        instack[u] = true;

        for(int e=g.head[u]; e!=-1; e=g.E[e].next){
            v = g.E[e].v;
            if(DFN[v] == -1){
                tarjan(g, v);
                low[u] = min(low[u], low[v]);
            }else if(instack[v]){
                low[u] = min(low[u], DFN[v]);
            }
        }

        if(DFN[u] == low[u]){
            ++bcnt;
            do{
                v = sta[--top];
                instack[v] = false;
                belong[v] = bcnt;
            }while(u != v);
        }
    }
    void scc(const Graph& g, const int n){
        idx = top = bcnt = 0;
        memset(DFN, -1, sizeof(DFN));
        memset(instack, 0, sizeof(instack));
        for(int i=0; i<n; ++i)
            if(DFN[i] == -1)
                tarjan(g, i);
    }
private:
    int idx, top, bcnt;
    int DFN[VN], low[VN], belong[VN], sta[VN];
    bool instack[VN];
    int color[VN], opp[VN], indeg[VN];
}sat;


int main(){

    char ch1, ch2;
    int a, b;
    while(~scanf("%d%d", &n, &m) && n+m){
        g.init();
        g.addEdge(n, 0); //注意要添加这个!因为新郎也可能有奸情
        for(int i=0; i<m; ++i){
            scanf("%d%c%d%c",&a,&ch1,&b,&ch2);
            if(ch1=='h' && ch2=='h'){
                g.addEdge(a, b+n);
                g.addEdge(b, a+n);
            }else if(ch1=='h' && ch2=='w'){
                g.addEdge(a, b);
                g.addEdge(b+n, a+n);
            }else if(ch1=='w' && ch2=='h'){
                g.addEdge(a+n, b+n);
                g.addEdge(b, a);
            }else if(ch1=='w' && ch2=='w'){
                g.addEdge(a+n, b);
                g.addEdge(b+n, a);
            }
        }

        if(!sat.check(g, n)) puts("bad luck");
        else{
            sat.toposort(g, g1, n);
        }

    }

    return 0;
}


分享到:
评论

相关推荐

    POJ1002-487-3279【Hash+Qsort】

    2. "POJ1002-487-3279【Qsort】.cpp":这个可能是单独实现快速排序部分的代码,可能用于比较不同的排序方法或作为哈希+快速排序方案的一部分。 3. "POJ1002-487-3279.doc":这是一个文档文件,很可能包含了详细的...

    POJ1258-Agri-Net【Prim】

    2. 建立一个空集合,将已加入最小生成树的顶点放入其中。 3. 对于图中其他未加入集合的顶点,找出与集合内顶点相连的边中权值最小的一条。 4. 将这条边的未加入顶点加入集合,更新边的最小权值。 5. 重复步骤3到4,...

    POJ2299-Ultra-QuickSort

    【标题】"POJ2299-Ultra-QuickSort"是北京大学在线判题系统POJ上的一道编程题目,其主要涉及的算法是快速排序(Ultra-QuickSort)。快速排序是一种高效的排序算法,由C.A.R. Hoare在1960年提出。它的基本思想是采用...

    POJ水题集--50道--增加自信

    POJ水题集-----50道左右-----增加自信啊..

    POJ3292-Semi-prime H-numbers

    【标题】"POJ3292-Semi-prime H-numbers"是一个编程竞赛题目,源自北京大学的在线判题系统POJ(Problem Set of Peking University)。这个题目主要涉及数论和算法设计,特别是关于半素数(Semi-prime)的概念以及H-...

    POJ3253-POJ3253-Fence Repair【STL优先队列】

    2. "POJ3253-POJ3253-Fence Repair【STL优先队列】.cpp":这是使用STL中的优先队列数据结构来解决题目的代码。 3. "POJ3253-POJ3253-Fence Repair【朴素思想TLE】.cpp":这个文件可能包含了没有利用优先队列,而是...

    POJ解题报告--1005

    ### POJ解题报告--1005 #### 题目概述 本题要求编写一个程序,模拟根据地块的半圆面积计算该地块开始侵蚀的年份。具体来说,对于每个地块,输入两个坐标值(x 和 y),分别表示地块在平面直角坐标系中的位置。然后...

    POJ1207-The 3n + 1 problem

    《POJ1207-The 3n + 1 problem》是北京大学在线编程平台POJ上的一道经典算法题目,其主要涉及的知识点是数论和动态规划。本题目的核心是解决著名的“Collatz Conjecture”问题,也被称为“3n+1猜想”。 3n+1猜想是...

    poj训练计划.doc

    根据给定的文件信息,我们可以总结出一份详细的IT知识训练计划,主要针对编程竞赛和算法学习,特别是聚焦于POJ(Problem Online Judge)平台上的题目训练。这份计划分为两个阶段,初级阶段和中级阶段,共计涉及了165...

    非常全的poj答案库 1164-1874 1000-4007

    标题中的“非常全的poj答案库 1164-1874 1000-4007”表明这是一个包含大量POJ(Problem Online Judge)编程竞赛题目解决方案的资源集合。POJ是北京大学主办的一个在线编程平台,它提供了一系列的编程题目供参赛者...

    poj 3131 Cubic Eight-Puzzle.md

    poj 3131 Cubic Eight-Puzzle.md

    ACM------搜索+(从入门到精通)

    非常详细的ACM 搜索类型题 配套POJ练习,有详细思路

    poj部分源码--Java

    poj平台有关数据结构题的Java源码 1159 1276 2406 2502 2509 2513 2533 2778 3176

    poj 2196 Specialized Four-Digit Numbers.md

    poj 2196 Specialized Four-Digit Numbers.md

    POJ3009-Curling 2.0【DFS+Vector+回溯+剪枝】

    《POJ3009-Curling 2.0:深度优先搜索、向量、回溯与剪枝的综合应用》 北京大学在线编程平台上的POJ3009题目名为"Curling 2.0",它是一道涉及到算法与数据结构的复杂问题,主要考察了参赛者对深度优先搜索(DFS)、...

    poj多道----acm----解题报告

    7. **输出结果**:最后,将总光照强度I总输出到输出文件,保留两位小数。 在实现这个算法时,需要注意浮点数运算的精度问题,以及处理边界情况,比如多边形的边可能与x轴平行,这时角度计算可能需要特别处理。此外...

    POJ2965-The Pilots Brothers' refrigerator

    在提供的代码文件中,"POJ2965-The Pilots Brothers' refrigerator(DFS+enum).cpp" 应该是使用DFS和枚举实现的解决方案,而 "POJ2965-The Pilots Brothers' refrigerator(DFS+Bit).cpp" 是使用DFS和位运算的版本。...

    POJ3733-Changing Digits【DFS+强剪枝】

    【描述】"北大POJ3733-Changing Digits【DFS+强剪枝】解题报告+AC代码"指的是对这个题目的解决方案进行分析和记录的文档,其中包含了解题思路、实现过程以及能够通过系统验证的正确代码。"AC"是Accepted的缩写,表示...

    POJ2002-Squares

    2. "POJ2002-Squares.doc":这可能是一个Microsoft Word文档,包含了详细的解题报告,可能包括问题分析、算法描述、解题步骤、运行结果和可能的优化措施等。 详细说明: 在"POJ2002-Squares"这个问题中,参赛者可能...

    POJ中缀-后缀-四则运算

    人们熟悉的四则运算表达式称为中缀表达式,例如(23+34*45/(5+6+7))。在程序设计语言中,可以利用堆栈的方法把中缀表达式转换成保值的后缀表达式(又称逆波兰表示法),并最终变为计算机可以直接执行的指令,得到...

Global site tag (gtag.js) - Google Analytics