POJ 3648 Wedding[2-SAT]

题意: 有一对 新人举办婚礼,邀请了n-1对夫妇,有一张很长的桌子,要求左右的夫妇都分别坐在桌子的两侧,且知道了 m 对 人有关系,要求新娘对面不能出现有关系的两个人。

分析: 在 有关系的人之间连边,在所有夫妇之间连边,用奇数表示男的,偶数表示女的,用2-sat方法染色,最后输出不在新娘一边的人。

#include<stdio.h>
#include<string.h>
#define op(x) ((x)=='h'?1:0)
#define clr(x)memset(x,0,sizeof(x))
#define min(a,b)(a)<(b)?(a):(b)
#define maxn 3005
struct node
{
    int to,next;
}e[1000000];
int tot;
int head[maxn];
void add(int s,int u)
{
    e[tot].to=u;
    e[tot].next=head[s];
    head[s]=tot++;
}
int n,m,ti,top,sn;
int dfn[maxn],low[maxn];
int ins[maxn],sta[maxn];
int vis[maxn],col[maxn];
void tar(int u)
{
    dfn[u]=low[u]=++ti;
    sta[++top]=u;
    ins[u]=1;
    int i,k;
    for(i=head[u];i;i=e[i].next)
    {
        k=e[i].to;
        if(!dfn[k])
        {
            tar(k);
            low[u]=min(low[u],low[k]);
        }
        else if(ins[k])
            low[u]=min(low[u],dfn[k]);
    }
    if(dfn[u]==low[u])
    {
        sn++;  // 强连通分支
        do
        {
            k=sta[top--];
            ins[k]=0;
            col[k]=sn; // 染色
        }
        while(k!=u);
    }
}
void dfs(int u)
{
    vis[u]=1;
    int i,k;
    for(i=head[u];i;i=e[i].next)
    {
        k=e[i].to;
        if(!vis[k])
            dfs(k);
        sta[++top]=u;
    }
}
int main()
{
    int i,k,flag,a,b;
    char c[2],d[2];
    while(scanf("%d%d",&n,&m),n||m)
    {
        top=ti=sn=0; tot=1;
        clr(head); clr(ins); clr(dfn);  clr(low); clr(col);
        while(m--)
        {
            scanf("%d%s%d%s",&a,c,&b,d);
            a=2*a;
            if(c[0]=='h')
                a+=1;
               b=2*b;
            if(d[0]=='h')
                b+=1;
            add(2*a+1,2*b);
            add(2*b+1,2*a);
        }
        for(i=0;i<n;i++)
        {
            add(4*i,4*i+3);
            add(4*i+3,4*i);
            add(4*i+1,4*i+2);
            add(4*i+2,4*i+1);
        }
        add(2,3); // 新郎,新娘
        for(i=0;i<4*n;i++)
            if(dfn[i]==0)
                tar(i);
        for(i=0;i<4*n;i+=2)
        {
            if(col[i]==col[i+1])
                break;
        }
        if(i!=4*n)
        {
            printf("bad luck\n");
            continue;
        }
        top=0;
        clr(vis);
        clr(col);
        for(i=0;i<4*n;i++)
            if(!vis[i])
                dfs(i);
        while(top)
        {
            k=sta[top--];
            if(col[k])
                continue;
            col[k]=2;
            col[k^1]=1;
        }
        flag=0;
        for(i=4;i<4*n;i+=2)
        {
            if(col[i]==2)
                continue;
            if(flag)
                printf(" ");
            flag=1;
            printf("%d",i/4);
            if(i%4>=2)
                printf("h");
            else printf("w");
        }
        printf("\n");
    }
    return 0;
}

 

posted @ 2012-08-04 23:56  'wind  阅读(228)  评论(0)    收藏  举报