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

POJ3905 Perfect Election【2-SAT】【Tarjan】

时间:2015-02-20 22:00:24      阅读:204      评论:0      收藏:0      [点我收藏+]

标签:

题目链接:

http://poj.org/problem?id=2914


题目大意:

有N个候选人,有M组要求,每组要求关系到候选中的两个人A和B,"+A +B"表示A和B中至少

有一人被选中,"-A -B"表示A和B中至少有一人不被选中。"+A -B"表示A被选中和B不被选中两

件事至少发生一件。"-A +B"表示A不被选中和B被选中至少发生一件。那么问题来了:是否存在

M组要求全部符合的方案。


思路:在本题中,每个人都有两种状态,一种是选中,一种是不选中。可以把一个人i拆成两个点

Pi和P(i+N),分别表示当选和落选。那么两个人i和j的关系就可以表示为以下四种:

i和j至少有一个人当选:i->j+N,j->i+N

i和j至少有一个人落选:i+N->j,j+N->i

i当选,j落选:              i->j,j+N->i+N

i落选,j当选:              i+N->j+N,j->i

那么根据上面的关系建有向图,那么问题就变为从图中选出N个点,并且Ai和A(i+N)的点不能同时

被选择,使其满足2-SAT条件。求出图的强连通分量,如果选中强连通分量中的一个点,那么就必

须选中强连通分量中的所有点,如果Ai和!Ai都在一个强连通分量里,则产生矛盾,那么2-SAT无解。

如果都不在一个强连通分量里,则2-SAT有解。最后的步骤就是用Tarjan了求强连通分量并缩点,之

后判断是否存在Ai和A(i+N)在一个强连通分量里。如果存在,则方案不满足,如果不存在,则方案

满足。


#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
const int MAXN = 2200;
const int MAXM = MAXN*MAXN;

struct EdgeNode
{
    int to;
    int next;
}Edges[MAXM];

int Head[MAXN];
int dfn[MAXN],low[MAXN],belong[MAXN],Stack[MAXN],vis[MAXN];
int m,id,lay,scc,N,M;

void AddEdges(int u,int v)
{
    Edges[id].to = v;
    Edges[id].next = Head[u];
    Head[u] = id++;
}

void TarBFS(int pos)
{
    dfn[pos] = low[pos] = ++lay;
    Stack[m++] = pos;
    vis[pos] = 1;

    for(int i = Head[pos]; i != -1; i = Edges[i].next)
    {
        int v = Edges[i].to;
        if( !dfn[v] )
        {
            TarBFS(v);
            low[pos] = min(low[pos],low[v]);
        }
        else if(vis[v])
            low[pos] = min(low[pos],low[v]);
    }
    int v;
    if(dfn[pos] == low[pos])
    {
        ++scc;
        do
        {
            v = Stack[--m];
            belong[v] = scc;
            vis[v] = 0;
        }while(v != pos);
    }
}

int main()
{
    int u,v;
    while(~scanf("%d%d",&N,&M))
    {
        id = m = scc = lay = 0;
        memset(Head,-1,sizeof(Head));
        memset(vis,0,sizeof(vis));
        memset(low,0,sizeof(low));
        memset(dfn,0,sizeof(dfn));
        memset(belong,0,sizeof(belong));
        for(int i = 0; i < M; ++i)
        {
            scanf("%d%d",&u,&v);
            int a = abs(u);
            int b = abs(v);

            if(u > 0 && v > 0)
            {
                AddEdges(a+N,b);
                AddEdges(b+N,a);
            }

            if(u < 0 && v < 0)
            {
                AddEdges(a,b+N);
                AddEdges(b,a+N);
            }

            if(u > 0 && v < 0)
            {
                AddEdges(a+N,b+N);
                AddEdges(b,a);
            }

            if(u < 0 && v > 0)
            {
                AddEdges(a,b);
                AddEdges(b+N,a+N);
            }
        }

        for(int i = 1; i <= 2*N; ++i)
            if( !dfn[i] )
                TarBFS(i);
        int ans = 1;
        for(int i = 1; i <= N; ++i)
        {
            if(belong[i] == belong[i+N])
            {
                ans = 0;
                break;
            }
        }

        printf("%d\n",ans);
    }

    return 0;
}



POJ3905 Perfect Election【2-SAT】【Tarjan】

标签:

原文地址:http://blog.csdn.net/lianai911/article/details/43890461

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