题意:给一个无向图,让你指定边的方向,比如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(); } }
版权声明:转载请注明出处
时间: 2024-10-16 22:52:16