POJ 3648 Wedding(2-SAT输出一组解)

来源:互联网 发布:qt mysql数据库 编辑:程序博客网 时间:2024/05/16 03:51

题意:有新郎新娘举办婚礼,吃饭的时候大家坐在一长方形桌,桌子有两列,新娘坐一列上看对面一列,她定义以下事情会让她不开心:夫妻都在对面一列或有仇人在对面一列。问是否能安排出合理方案使得新娘开心。如果有,输出YES并且输出新娘这一列坐着的人,否则输出bad luck。

解法:夫妻不能在同一列,所以夫妻要不在新娘这排要不不在新娘这排,用2-SAT可以很好满足这个条件。然后读入仇人的信息,标记好,用2-sat判断下是否存在解即可。但是他是要输出和新娘同一排的人,那么想到之前做了一道2-sat输出最小字典序的模板,直接套上来用。

代码如下:

#include<iostream>#include<cstring>#include<cstdio>const int maxn = 50000 * 2;const int maxm = 500100;using namespace std;int n, m;int s[maxn], cnt;bool mark[maxn];int head[maxn], to[maxm << 1], nx[maxm << 1], tot;void addedge(int u, int v) {    to[tot] = v, nx[tot] = head[u], head[u] = tot++;}void init() {    tot = 0;    memset(head, -1, sizeof(head));    memset(mark, 0, sizeof(mark));}bool dfs(int u) {    if(mark[u ^ 1]) return false;    if(mark[u]) return true;    s[++cnt] = u;    mark[u] = 1;    for(int i = head[u]; ~i; i = nx[i]) {        if(!dfs(to[i]))            return false;    }    return true;}bool twosat() {mark[0] = 1;    for(int i = 1; i <=n-1; i++){int u=i*2;if(mark[u]||mark[u+1])continue;        cnt=0;if(!dfs(u)){while(cnt)mark[s[cnt--]]=0;        if(!dfs(u+1)){return false;}}}return true;}int main() {    while(scanf("%d%d", &n, &m) && n && m){        init();        while(m--) {        int u, v;        char c1, c2;            scanf("%d%c%d%c", &u, &c1, &v, &c2);            u = u * 2 + (c1 == 'h');            v = v * 2 + (c2 == 'h');            addedge(u ^ 1, v);            addedge(v ^ 1, u);        }                if(twosat()) {            for(int i = 1; i < n; i++) {                printf("%d%c ", i, mark[i * 2] ? 'w' : 'h');            }            printf("\n");        } else {            printf("bad luck\n");        }    }    return 0;}


原创粉丝点击