码迷,mamicode.com
首页 > 其他好文 > 详细

POJ 3648 Wedding (2-SAT+输出可行解)

时间:2014-11-11 16:43:31      阅读:278      评论:0      收藏:0      [点我收藏+]

标签:acm   c语言   算法   编程   2-sat   

题目地址:POJ 3648

这题终于AC了。。。。没有专门对新郎新娘加一条边。。

这题前面一直读错题意了,调试了好长时间样例也没过。。这题的意思是只要新郎那一边没有通奸的就可以,然后输出新娘那一边的人。

然后就是对那些有**关系的加边,由于新郎新娘必须要在两侧,所以最后要额外加一条边。然后用强连通判断,逆拓扑染色输出可行解即可。

代码如下:

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#include <queue>
#include <map>
#include <set>
#include <algorithm>

using namespace std;
#define LL __int64
const int INF=0x3f3f3f3f;
int head[2001], cnt, ans, top, index;
int dfn[2100], low[2100], belong[2100], instack[2100], stak[2100];
struct node
{
    int u, v, next;
}edge[1000000];
void add(int u, int v)
{
    edge[cnt].v=v;
    edge[cnt].next=head[u];
    head[u]=cnt++;
}
void tarjan(int u)
{
    dfn[u]=low[u]=++index;
    instack[u]=1;
    stak[++top]=u;
    for(int i=head[u];i!=-1;i=edge[i].next)
    {
        int v=edge[i].v;
        if(!dfn[v])
        {
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(instack[v])
        {
            low[u]=min(low[u],dfn[v]);
        }
    }
    if(dfn[u]==low[u])
    {
        ans++;
        while(1)
        {
            int v=stak[top--];
            instack[v]=0;
            belong[v]=ans;
            if(u==v) break;
        }
    }
}
int head1[2100], cnt1, in[2100], ct[2100], color[2100], c[2100], tot;
struct N
{
    int u, v, next;
}edge1[1000000];
void add1(int u, int v)
{
    edge1[cnt1].v=v;
    edge1[cnt1].next=head1[u];
    head1[u]=cnt1++;
}
void topo(int n)
{
    int i;
    queue<int>q;
    for(i=1;i<=ans;i++)
    {
        if(!in[i])
            q.push(i);
    }
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        if(!color[u])
        {
            color[u]=1;
            color[ct[u]]=-1;
        }
        for(i=head1[u];i!=-1;i=edge1[i].next)
        {
            int v=edge1[i].v;
            in[v]--;
            if(!in[v])
                q.push(v);
        }
    }
}
void init()
{
    memset(head,-1,sizeof(head));
    cnt=ans=top=index=0;
    memset(dfn,0,sizeof(dfn));
    memset(instack,0,sizeof(instack));
    memset(head1,-1,sizeof(head1));
    cnt1=0;
    memset(in,0,sizeof(in));
    memset(color,0,sizeof(color));
}
int main()
{
    int n, m, i, j, len1, len2, x, y;
    char s1[10], s2[10];
    while(scanf("%d%d",&n,&m)!=EOF&&n+m)
    {
        init();
        while(m--)
        {
            scanf("%s%s",s1,s2);
            len1=strlen(s1);
            len2=strlen(s2);
            x=y=0;
            for(i=0;i<len1-1;i++)
                x=x*10+s1[i]-'0';
            for(i=0;i<len2-1;i++)
                y=y*10+s2[i]-'0';
            x<<=1;
            y<<=1;
            if(s1[len1-1]=='w')
                x++;
            if(s2[len2-1]=='w')
                y++;
                //printf("%d %d\n",x,y);
            add(x,y^1);
            add(y,x^1);
        }
        add(1,0);
        for(i=0;i<n<<1;i++)
        {
            if(!dfn[i])
                tarjan(i);
        }
        int flag=0;
        for(i=0;i<n;i++)
        {
            if(belong[i<<1]==belong[i<<1|1])
            {
                flag=1;
                break;
            }
            ct[belong[i<<1]]=belong[i<<1|1];
            ct[belong[i<<1|1]]=belong[i<<1];
        }
        if(flag)
            puts("bad luck");
        else
        {
            for(i=0;i<n<<1;i++)
            {
                for(j=head[i];j!=-1;j=edge[j].next)
                {
                    int v=edge[j].v;
                    if(belong[i]!=belong[v])
                    {
                        add1(belong[v],belong[i]);
                        in[belong[i]]++;
                    }
                }
            }
            topo(n);
            tot=0;
            for(i=2;i<n<<1;i++)
            {
                if(color[belong[i]]==-1)
                {
                    c[tot++]=i;
                }
            }
            for(i=0;i<tot;i++)
            {
                if(c[i]&1)
                    printf("%dw",c[i]/2);
                else
                    printf("%dh",c[i]/2);
                    if(i!=tot-1)
                        printf(" ");
            }
            puts("");
            /*for(i=0;i<n<<1;i++)
            {
                printf("%d ",color[belong[i]]);
            }
            puts("");*/
        }
    }
    return 0;
}


POJ 3648 Wedding (2-SAT+输出可行解)

标签:acm   c语言   算法   编程   2-sat   

原文地址:http://blog.csdn.net/scf0920/article/details/41011191

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!