您的位置:首页 > 其它

hdu 3602 Party (2-sat)

2015-07-20 16:30 155 查看
题目链接:

点击打开链接

题目大意:

给出一些家庭,家庭中有***,然后有些人之间有矛盾,是不能一起一起开会的,那么这些家庭只派一个代表能不能开一个社区会议

题目分析:

因为如果存在点Ai必须选Bj,那么选了Bi也一定要选Aj,那么就出现了对称的图,因为每个强连通分量的点的值必须一致,所以任意Ai和Aj如果在同一个强连通分量中,那么就矛盾,因为Ai和Aj一定是不能相同的,如果不出现矛盾的情况,那么就是有解,出现了矛盾就是无解

代码如下:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <stack>
#define MAX 2005

using namespace std;

int mark[MAX],dfn[MAX],low[MAX],belong[MAX],times,cnt;
vector<int> e[MAX];
stack<int> s;

void tarjan ( int u )
{
    dfn[u] = low[u] = ++times;
    mark[u] = 1;
    s.push ( u );
    int len = e[u].size();
    for ( int i = 0 ; i < len ; i++ )
    {
         int v = e[u][i];
         if ( !mark[v] )
         {
             tarjan ( v );
             low[u] = min ( low[u] , low[v] );
         }
         if ( mark[v] == 1 )
            low[u] = min ( low[u] , dfn[v] );
    }
    if ( dfn[u] == low[u] )
    {
        int temp;
        do
        {
            temp = s.top();
            belong[temp] = cnt;
            mark[temp] = 2;
            s.pop();
        }while ( temp != u );
        cnt++;
    }
}

void init ( )
{
    memset ( mark , 0 , sizeof ( mark ));
    for ( int i = 0 ; i < MAX ; i++ )
        e[i].clear();
    while ( !s.empty()) s.pop();
    times = cnt = 0;
}

int n,m;

int main ( )
{
    int a , b , c , d;
    while ( ~scanf ( "%d%d" , &n , &m ) )
    {
        init();
        while ( m-- )
        {
            scanf ( "%d%d%d%d" , &a , &b , &c , &d );
            e[2*a+c].push_back ( 2*b+1-d );
            e[2*b+d].push_back ( 2*a+1-c );
        }

        for ( int i = 0 ; i < 2*n ; i++ )
            if ( !mark[i] ) tarjan ( i );

        bool flag = true;
        for ( int i = 0 ; i < n ; i++ )
            if ( belong[i<<1] == belong[i<<1|1] )
                flag = false;

        puts ( flag?"YES":"NO" );

    }
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: