poj 3648 Wedding

来源:互联网 发布:人工智能医疗股票龙头 编辑:程序博客网 时间:2024/06/03 03:31

类型:2-sat

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

来源:Waterloo Local Contest, 2007.9.29

思路:每个人都有可能坐在左边或者右边,将其分为两个点i, i + 2 * n。定义新娘在左侧。

(1)对于一对有暧昧关系的人i, j。如果i在右边,必有j在左边,如果j在右边,必有i在左边。构造有向边: addedge1(i + 2 * n, j);  addedge1(j + 2 * n, i)。

(2)夫妇需一左一右

然后通过2-sat算法判断可行性,如果可行并输出解。

!!!新娘必在左边,新郎必在右边。构造有向边 addedge1(2 * n + 1, 1); addedge1(n + 1, 3 * n + 1);

// poj 3648 Wedding// wa wa ac 196K 0MS#include <iostream>#include <string>#include <queue>#include <stack>#include <algorithm>#include <cmath>#include <cstdio>#include <cstdlib>#include <cstring>using namespace std;#define FOR(i,a,b) for(i = (a); i < (b); ++i)#define FORE(i,a,b) for(i = (a); i <= (b); ++i)#define FORD(i,a,b) for(i = (a); i > (b); --i)#define FORDE(i,a,b) for(i = (a); i >= (b); --i)#define CLR(a,b) memset(a,b,sizeof(a))#define PB(x) push_back(x)const int N = 200;const int M = 40010;int low[N], dfn[N];int belong[N];bool inStack[N], vis[N];stack<int> st;int n, m;int step, t;int conflict[N];//缩点后有矛盾的点int du[N];//入度int color[N];//1为红色,-1为蓝色,红色输出int cnt1, cnt2;int head1[N], head2[N];int top[N], cnt;struct node {    int s, e;    int len;}c[N];struct edge1 {    int v, nxt;}E1[M];struct edge2 {    int v, nxt;}E2[M];void addedge1(int u, int v) {    E1[cnt1].v = v;    E1[cnt1].nxt = head1[u];    head1[u] = cnt1++;}void addedge2(int u, int v) {    E2[cnt2].v = v;    E2[cnt2].nxt = head2[u];    head2[u] = cnt2++;}void tarjan(int u) {    int i;    step++;    st.push(u);    low[u] = dfn[u] = step;    vis[u] = 1;    inStack[u] = 1;    for(i = head1[u]; i != -1; i = E1[i].nxt) {        int x = E1[i].v;        if(!vis[x]) {            tarjan(x);            low[u] = min(low[u], low[x]);        }        else if(inStack[x])            low[u]=min(low[u], dfn[x]);    }    if(low[u] == dfn[u]) {        t++;        while(1) {            int x = st.top();            st.pop();            belong[x] = t;            inStack[x] = 0;            if(x == u)                break;        }    }}void init() {    cnt1 = cnt2 = step = t = 0;    CLR(head1, -1);    CLR(head2, -1);    CLR(du, 0);    CLR(color, 0);    CLR(vis, 0);    CLR(inStack, 0);}bool isConflict(int a, int b, int c, int d) {    if(a >= d || b <= c)        return false;    return true;}void Rebuild(){//逆图    int i, j;    FORE(i, 1, 4 * n) {        for(j = head1[i]; j != -1; j = E1[j].nxt) {            int a = belong[i], b = belong[E1[j].v];            if(a != b) {                addedge2(b, a);                du[a]++;            }        }    }    FORE(i, 1, 2 * n) {        int a = belong[i], b = belong[i + 2 * n];        conflict[a] = b;        conflict[b] = a;    }}void topsort() {    int i,j;    queue<int> q;    FORE(i, 1, t)        if(du[i] == 0)            q.push(i);    cnt = 0;    while(!q.empty()) {        int x = q.front();        top[++cnt] = x;        q.pop();        for(i = head2[x]; i != -1; i = E2[i].nxt) {            int tmp = E2[i].v;            du[tmp]--;            if(du[tmp] == 0)                q.push(tmp);        }    }}void dfs_Blue(int u) {    int i;    color[u] = -1;    for(i = head2[u]; i != -1; i = E2[i].nxt) {        int x = E2[i].v;        if(color[x] == 0)            dfs_Blue(x);    }}void dfs_Red() {    int i, j;    FORE(i, 1, cnt) {        int x = top[i];        if(color[x] == 0) {            color[x] = 1;            dfs_Blue(conflict[x]);        }    }}void output() {    int i, j, t1, t2;    int len = 0;    int sign = color[belong[1]];    FORE(i, 2, 2 * n) {        int x = belong[i], y = belong[i + 2 * n];        if(color[x] == sign) {            if(i <= n)                (len++ == 0) ? printf("%dw", i - 1) : printf(" %dw", i - 1);            else                (len++ == 0) ? printf("%dh", i - n - 1) : printf(" %dh", i - n - 1);        }    }    printf("\n");}void solve() {    int i, j;    FORE(i, 1, 4 * n)        if(!vis[i])            tarjan(i);    FORE(i, 1, 2 * n) {        if(belong[i] == belong[i + 2 * n]) {            printf("bad luck\n");            return ;        }    }    Rebuild();    topsort();    dfs_Red();    output();}int main() {    char str1[5], str2[5];    while(scanf("%d %d", &n, &m) != EOF, n || m) {        init();        int i, j, t1, t2;        FORE(i, 1, m) {            scanf("%d%c%d%c", &t1, &str1[0], &t2, &str2[0]);            ++t1, ++t2;            if(str1[0] == 'h')                t1 += n;            if(str2[0] == 'h')                t2 += n;            addedge1(t1 + 2 * n, t2);            addedge1(t2 + 2 * n, t1);        }        addedge1(2 * n + 1, 1);        addedge1(n + 1, 3 * n + 1);        FORE(i, 1, n) {            addedge1(i, i + 3 * n);            addedge1(i + 2 * n, i + n);            addedge1(i + n, i + 2 * n);            addedge1(i + 3 * n, i);        }        solve();    }    return 0;}






原创粉丝点击