poj 3648 Wedding(2-sat--拓扑排序输出可行解)

题目链接:

点击打开链接

题目大意:

给出n对父亲,第0对是新郎新娘,其中有的两个人有**关系,不能坐在一起,夫妻不能坐在一起,问最终应当如何做,随便给出一种方案即可。

题目分析:

2-sat模板题,建边是选谁之后必选谁,也就是i和j不能同坐,那么i->j' , j->i'两条边需要建立,求解啥的直接上模板,简单粗暴

代码如下:

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

using namespace std;

vector<int> e[MAX];
vector<int> g[MAX];
stack<int> s;
bool vis[MAX];
bool inStack[MAX];
int low[MAX],dfn[MAX];
int belong[MAX];
int n,m,step,t;
int conflict[MAX];
int col[MAX];
int in[MAX];

void init ( )
{
    for ( int i = 0 ; i <= 2*n ; i++ )
    {
        e[i].clear();
        vis[i] = 0;
        inStack[i] = 0;
        in[i] = 0;
        g[i].clear();
        col[i] = 0;
    }
    while ( !s.empty()) s.pop();
}

void add ( int a , int b )
{
    e[a].push_back ( b );
}

void tarjan ( int u )
{
    vis[u] = true;
    step++;
    s.push ( u );
    inStack[u] = true;
    low[u] = dfn[u] = step;
    for ( int i = 0 ; i < e[u].size() ; i++ )
    {
        int v = e[u][i];
        if ( !vis[v] )
        {
            tarjan ( v );
            low[u] = min ( low[u] , low[v] );
        }
        else if ( inStack[v] )
            low[u] = min ( low[u] , dfn[v] );
    }
    if ( low[u] == dfn[u] )
    {
        t++;
        while ( true )
        {
            int v = s.top();
            s.pop();
            belong[v] = t;
            inStack[v] = false;
            if ( v == u ) break;
        }
    }
}

//反向建图
void rebuild ( )
{
    for ( int i = 0 ; i < 2*n ; i++ )
        for ( int j = 0 ; j < e[i].size() ; j++ )
        {
            int a = belong[i],b=belong[e[i][j]];
            if ( a != b )
            {
                in[a]++;
                g[b].push_back ( a );
            }
        }
}

void topsort ( )
{
    int i,j;
    queue<int> q;
    for ( int i = 1 ; i < t ; i++ )
    {
        if (!in[i])
            q.push ( i );
    }
    while (!q.empty())
    {
        int u = q.front();
        q.pop();
        if ( !col[u] )
        {
            col[u] = 1;
            col[conflict[u]] = 2;
        }
        for ( int i = 0 ; i < g[u].size(); i++ )
        {
            int v = g[u][i];
            in[v]--;
            if ( !in[v] ) q.push ( v );
        }
    }
}

void solve ( )
{
    t = 0,step = 0;
    for ( int i = 0 ; i < 2*n ; i++ )
        if (!vis[i])
            tarjan ( i );
    for ( int i = 0 ; i < 2*n ; i += 2 )
    {
        if ( belong[i] == belong[i+1])
        {
            puts("bad luck");
            return;
        }
        int a = belong[i] , b = belong[i+1];
        conflict[a] = b;
        conflict[b] = a;
    }
    rebuild ();
    topsort ();
    for ( int i = 2 ; i < 2*n ; i += 2 )
    {
        if ( i != 2 ) printf ( " ");
        if ( col[belong[i]] == col[belong[0]])
            printf ( "%dw" , i/2 );
        else printf ( "%dh" , i/2 );
    }
    puts ( "");
}

int main ( )
{
    while ( ~scanf ( "%d%d" , &n , &m ) , n+m )
    {
        init ();
        char c1,c2;
        int d1,d2;
        int i,j,ii,jj;
        while ( m-- )
        {
            scanf ( "%d%c %d%c" , &d1 , &c1 , &d2 , &c2 );
            if ( c1 == 'h' )
            {
                i = 2*d1+1;
                ii = i-1;
            }
            else
            {
                i = 2*d1;
                ii = i+1;
            }
            if ( c2 == 'h' )
            {
                j = 2*d2+1;
                jj = j-1;
            }
            else
            {
                j = 2*d2;
                jj = j+1;
            }
            add ( i , jj );
            add ( j , ii );
        }
        add ( 0 , 1 );
        solve ( );
    }
    return 0 ;
}



你可能感兴趣的:(C++,图论,2-sat)