首页 > 代码库 > uva 11294 2-SAT问题

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;
}