uva 11294 2-SAT问题

英文太差了, 这个题目愣是半天没看懂 , 后面看别人翻译才看懂 ,  英语是硬伤啊

题目大意:给 n 对夫妇安排座位 , 0h , 0w表示新郎新娘 , 新娘只能看到坐在她对面那一排的人 , 要求:

1、同一对新郎新娘不能做在同一侧

2、有m对人互为通奸(可以男男、女女、男女) , 新娘不能同时看到互为通奸的两个人。

注意:新郎也有可能和其他人通奸

做法:

1、分两种情况讨论 , 新娘在左侧 ,
新娘在右侧 , 分别建图进行 2-SAT算法

2、不分左侧还是右侧 , 只分和新娘同侧或不同侧

下面给出做法一的代码

#include <iostream>
#include <vector>
#include <stdio.h>
#include <string.h>
using namespace std;

#define maxn 200000

int n , m;
int a[maxn][2];
vector<int>grap[maxn];
bool mark[maxn];
int s[maxn];
int c;

void init()
{
    memset(mark , 0 , sizeof(mark));
    for(int i = 0; i < 4*n; i++)
        grap[i].clear();
}

void add_edge(int x , int y)
{
    grap[x].push_back(y);
    //cout<<x<<",,"<<y<<endl;
}

bool dfs(int u)
{
    if(mark[u^1])  return false;
    if(mark[u])  return true;

    mark[u] = true;
    s[c++] = u;
    for(int i = 0; i < grap[u].size(); i++)
    {
        if(!dfs(grap[u][i]))  return false;
    }
    return true;
}

bool slove()
{
    int i;
    for(i = 0; i < n*4; i += 2)
    {
        if(!mark[i] && !mark[i+1])
        {
            c = 0;
            if(!dfs(i))
            {
                while(c > 0) mark[s[--c]] = false;
                if(!dfs(i+1))  return false;
            }
        }
    }
    return true;
}

void print(int i)
{
    int bz = true;
    for( ; i < 4*n ; i += 2)
    {
        if(i == 2*n || i == 2*n+1)  continue;
        if(mark[i])
        {

           if(i >= 2*n)
            {
                if(bz)  printf("%dh" , (i-2*n)/2) , bz = false;
                else printf("% dh" , (i-2*n)/2);
            }
            else
            {
                if(bz)  printf("%dw" , i/2) , bz = false;
                else printf("% dw" , i/2);
            }
        }
    }
    cout<<endl;
}

int main()
{
    while(scanf("%d %d" , &n , &m) != EOF)
    {
        if(n == 0 && m == 0)  break;
        //n -= 1;
        init();
        int i ;
        int x , y;
        char px , py;
        for(i = 0; i < m; i++)
        {
            scanf("%d%c %d%c" , &x , &px , &y , &py);
            //x -= 1; y -= 1;
            if(px == ‘h‘)  a[i][0] = 2*n+x*2;
            else a[i][0] = x*2;
            if(py == ‘h‘)  a[i][1] = 2*n+y*2;
            else a[i][1] = y*2;
        }

        for(i = 2; i < 2*n; i += 2) //夫妻之间
        {
            add_edge(i , 2*n+i+1);
            add_edge(2*n+i+1,i  );
            add_edge(i+1 , 2*n+i);
            add_edge(2*n+i , i+1);
        }
        for(i = 0; i < m; i++)  //仇人之间
        {
            add_edge(a[i][0]+1 , a[i][1]);
            add_edge(a[i][1]+1 , a[i][0]);
        }
        mark[0] = mark[2*n+1] = true;
        bool bz = slove();

        if(!bz)
        {
            init();
            for(i = 0; i < 2*n; i += 2) //夫妻之间
            {
                add_edge(i , 2*n+i+1);
                add_edge(2*n+i+1 ,i  );
                add_edge(i+1 , 2*n+i);
                add_edge(2*n+i , i+1);
            }
            for(i = 0; i < m; i++)  //仇人之间
            {
                add_edge(a[i][0] , a[i][1]+1);
                add_edge(a[i][1] , a[i][0]+1);
            }
            mark[1] = mark[2*n] = true;
            bz = slove();
            if(!bz)  printf("bad luck\n");
            else
            {
                print(3);
            }

        }
        else
        {
            print(2);
        }
    }
    return 0;
}

uva 11294 2-SAT问题,码迷,mamicode.com

时间: 2024-10-12 06:33:05

uva 11294 2-SAT问题的相关文章

UVA 11294 - Wedding(Two-Set)

UVA 11294 - Wedding 题目链接 题意:有n对夫妻,0号是公主.如今有一些通奸关系(男男,女女也是可能的)然后要求人分配在两側.夫妻不能坐同一側.而且公主对面一側不能有两个同奸的人,问方案 思路:2-set,建图.一共2n个人,设偶数是丈夫,奇数是妻子.左側为false,右側为true,然后丈夫妻子建一条true false 或 false true的边,然后然公主在左側.那么同奸的一对至少一个为false,建一条边,然后2-set判定就可以 代码: #include <cstd

UVa 11294 - Wedding

题目:有一场婚礼,有n对夫妇参加,他们之间有些人之间有奸情(可能同性),在场的人中有一个公主, 她清楚其他人的人际关系,问能否安排座位使得两边都是n个人,且公主看不见有奸情的人同时在的对面. 分析:2-SAT.直接按照看的流程敲的程序. 1.建图,矛盾的点建立对应的边(与一直关系相反): 2.利用Tarjan算法计算强连通分量,缩点: 3.判断是否有解(是否有夫妇在同一集合): 4.如果成立,利用拓扑排序求出一组解,输出. 说明:第一个2SAT(⊙_⊙). #include <algorithm

UVA 11294 POJ 3648 Wedding

题意: 婚礼上新郎新娘坐在桌子两侧  新娘只能看见对面的人  已知一些人有XX关系-  新娘不想看见有关系的同时坐在对面  问  满足条件的情况下  新娘这边做的人是谁 思路: 新郎那一边的约束最多  有利于解题  那么就变成了  一个人要不要坐新郎这边的2-sat问题  因此可以先求新郎这边的人  然后反一下就是新娘这边的了  注意  新郎是必选点  而且  不能选和新郎有XX关系的- 代码: #include<cstdio> #include<cstring> #include

UVA - 11294 Wedding(2-SAT)

题目大意:有N-1对夫妻参加一个婚宴,所有人都坐在一个长长的餐桌左侧或者右侧,新郎和新娘面做面坐在桌子的两侧.由于新娘的头饰很复杂,她无法看到和她坐在同一侧餐桌的人,只能看到对面餐桌的人.任意一对夫妻不能坐在桌子的同侧,另外有m对人吵过架,而新娘不希望看到两个吵过架的人坐在他的对面,问如何安排这些座位 解题思路:设mark[2*i]被标记时表示的是第i对夫妻的妻子跟新娘坐在同一侧,mark[2 * i + 1]被标记时表示的是第i对夫妻的丈夫跟新娘坐同一侧 设吵架的两人是i和j 如果吵过架的人都

uva 11294

Problem E: Wedding Up to thirty couples will attend a wedding feast, at which they will be seated on either side of a long table. The bride and groom sit at one end, opposite each other, and the bride wears an elaborate headdress that keeps her from

UVA 11488 Hyper Prefix Sets (Trie)

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2483 Hyper Prefix Sets Prefix goodness of a set string islength of longest common prefix*number of strings in the set.For example the prefix goodnes

uva 1564 - Widget Factory(高斯消元+逆元)

题目链接:uva 1564 - Widget Factory 题目大意:n种零件,m次工作日程,零件序号从1到n,给出m次工作日程的信息,x,s,e,表示生产了x个零件,从星期s开始到星期e(有可能是多个星期),然后给出生产的x个零件的序号.求每个零件被生产需要多少天(保证在3到10天) 解题思路:因为不能确定每个工作日程具体生产了几天,所以对应列出的方程均为线性模方程(模7),所以在高斯消元的过程中遇到除法要转换成乘上逆元. #include <cstdio> #include <cs

UVA 10679 I love Strings!!!(AC自动机)

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1620 题意: 给出一个文本串和若干个模式串,问模式串是否在文本串中出现过. 分析: 简单粗暴的AC自动机模板题,要注意模式串可能有重复的情况. /* * * Author : fcbruce * * Time : Sat 04 Oct 2014 03:30:15 PM CST * */ #i

UVA 1564 - Widget Factory(高斯消元)

UVA 1564 - Widget Factory 题目链接 题意:n种零件, 给定m个制作时间,每段时间制作k个零件,每种零件有一个制作时间,每段时间用Mon到Sun表示,求每个零件的制作时间,还要判断一下多解和无解的情况 思路:对于每段时间列出一个方程,这样一共列出m个方程解n个变元,利用高斯消元去求解,注意每个方程都是MOD 7的,所以在高斯消元过程中遇到除法要求该数字%7的逆元去进行运算 代码: #include <cstdio> #include <cstring> #i