HDU5348

题意:给一个无向图,让你指定边的方向,比如a→b为1,a←b为0,在给所有边指定方向后,对无向图上的每个顶点,如果满足|出度-入度|<2,那么输出一种方案。

思路:从结论入手,|出度-入度|<2,那么只能为0或1,对于0的情况,应该是出度等于入度,所以每个顶点都有偶数个度,既偶数条边,如果为1的话,一定是奇数条边,所以对于第二种情况,因为奇数边的点要么是起点,要么是终点(搜索),我们先对奇数边的点dfs,然后更改奇数边点的度数(删边),使之全部为偶数边,用line来存储相关联的两条边,index存储边的下标,value存储边的方向,total存放点的总度数。


#include <iostream>
#include <stdio.h>
#include <cstring>
#include <vector>
#define MAX 500050
using namespace std;


vector<int> line[MAX],index[MAX],value[MAX];
int total[MAX],flag[MAX],ans[MAX];
int t,n,m;


void init ()
{
    for ( int i = 0 ; i <= n ; i++ )
    {
        line[i].clear();
        index[i].clear();
        value[i].clear();
    }
    memset ( total , 0 , sizeof ( total ));
    memset ( flag , 0 , sizeof ( flag ));
}


void dfs ( int u )
{
    int len = line[u].size()-1;
    for ( int i = len ; i >= 0; i-- )
    {
        int v = line[u][i];
        int x = index[u][i];
        int c = value[u][i];
        line[u].pop_back();
        if ( flag[x] ) continue;
        total[u]--;
        total[v]--;
        ans[x] = c;
        flag[x] = 1;
        dfs ( v );
        break;
    }
}


void solve()
{
    for ( int u=1 ; u<=n;u++ )
        if (total[u]&1)
            dfs(u);
    for (int u=1;u<=n;u++)
        dfs(u);
    for (int i=0;i<m;i++ )
        printf("%d\n",ans[i]);
}


int main ( )
{
    scanf ( "%d" , &t );
    while ( t-- )
    {
        scanf ("%d%d" , &n , &m );
        init();
        for ( int i = 0 ; i < m ; i++ )
        {
            int u,v;
            scanf ( "%d%d" , &u , &v );
            line[u].push_back ( v );
            index[u].push_back ( i );
            value[u].push_back ( 1 );
            line[v].push_back ( u );
            index[v].push_back ( i );
            value[v].push_back ( 0 );
            total[u]++;
            total[v]++;
        }
        solve();
    }
}




posted @ 2015-08-06 10:43  __夜风  阅读(164)  评论(0编辑  收藏  举报