【代码】POJ 2762
2013-01-17 15:53
253 查看
// 题目来源:POJ 2762 // 题目大意:给定一个有向图,问该图是否弱连通(若图中任意两点之间可以到达,即可以i到j或者j到i,该图即为弱连通) // 解决方法:强连通分量缩点,当且仅当该图的拓扑序列唯一的时候才成立,那么只需记录当前入度为0的个数,当多于1个时不成立 #include <cstdio> #include <string> #define _ 60002 #define o 10002 using namespace std; void link( int, int ); void link2( int, int ); void tarjan( int ); bool judge( ); void topsort( int ); int dfn[ o ], low[ o ], h[ o ], h2[ o ], id[ o ], od[ o ], stack[ o ], code[ o ]; int next[ _ ], g[ _ ], next2[ _ ], g2[ _ ]; int q, n, m, t, t2, top, cnt, index, sid; bool ins[ o ]; bool flag; int main( ) { freopen( "2762.in", "r", stdin ); freopen( "2762.out", "w", stdout ); scanf( "%d", &q ); int aa, bb; while( q-- ) { memset( dfn, 0, sizeof( dfn ) ); memset( low, 0, sizeof( low ) ); memset( next, 0, sizeof( next ) ); memset( h, 0, sizeof( h ) ); memset( next2, 0, sizeof( next2 ) ); memset( h2, 0, sizeof( h2 ) ); memset( id, 0, sizeof( id ) ); memset( od, 0, sizeof( od ) ); memset( code, 0, sizeof( code ) ); t = 0; t2 = 0; cnt = 0; scanf( "%d%d", &n, &m ); for( int i = 1; i <= m; i++ ) { scanf( "%d%d", &aa, &bb ); link( aa, bb ); } for( int i = 1; i <= n; i++ ) if( !dfn[ i ] ) tarjan( i ); if( judge( ) ) printf( "Yes\n" ); else printf( "No\n" ); } return 0; } void link( int aa, int bb ) { next[ ++t ] = h[ aa ]; h[ aa ] = t; g[ t ] = bb; } void link2( int aa, int bb ) { next2[ ++t2 ] = h2[ aa ]; h2[ aa ] = t2; g2[ t2 ] = bb; } void tarjan( int i ) { int j; dfn[ i ] = low[ i ] = ++index; stack[ ++top ] = i; ins[ i ] = true; for( int k = h[ i ]; k; k = next[ k ] ) { j = g[ k ]; if( !dfn[ j ] ) { tarjan( j ); if( low[ j ] < low[ i ] ) low[ i ] = low[ j ]; } else if( ins[ j ] && dfn[ j ] < low[ i ] ) low[ i ] = dfn[ j ]; } if( low[ i ] == dfn[ i ] ) { cnt++; do { j = stack[ top-- ]; code[ j ] = cnt; ins[ j ] = false; } while( i != j ); } } bool judge( ) { int j; flag = true; sid = 0; for( int i = 1; i <= n; i++ ) for( int k = h[ i ]; k; k = next[ k ] ) { j = g[ k ]; if( code[ i ] != code[ j ] ) { id[ code[ j ] ]++; link2( code[ i ], code[ j ] ); } } for( int i = 1; i <= cnt; i++ ) if( id[ i ] == 0 ) sid++; if( sid > 1 ) return 0; for( int i = 1; i <= cnt; i++ ) if( id[ i ] == 0 ) topsort( i ); if( flag ) return 1; return 0; } void topsort( int i ) { int j; sid--; id[ i ] = -1; for( int k = h2[ i ]; k; k = next2[ k ] ) { j = g2[ k ]; id[ j ]--; if( id[ j ] == 0 ) sid++; } if( sid > 1 ) flag = false; for( int k = h2[ i ]; k; k = next2[ k ] ) { j = g2[ k ]; if( id[ j ] == 0 ) topsort( j ); } }
相关文章推荐
- POJ 2762 Going from u to v or from v to u? / 强连通分量&&拓扑
- poj&nbsp;2447&nbsp;代码改正
- 【poj 3461】 Oulipo 中文题意&题解&代码(C++)
- POJ 2762 Going from u to v or from v to u?(有向图单向连通)
- poj 2762 Going from u to v or from v to u?
- POJ 2762 Going from u to v …(强连通分量+拓扑排序)
- POJ 2845 01000001 二进制加法 套用高精度加法运算代码
- POJ2762 Going from u to v or from v to u?(强连通缩点+拓扑排序)
- 【poj 1426】Find The Multiple 题意&题解&代码(C++)
- poj 2762
- POJ 2762 Going from u to v or from v to u? (图论-tarjan)
- POJ1451 T9 题解&代码
- poj 2528【区间更新,区间统计,离散化,下面代码是WA的,弄好多天了,错在那里呢,希望高手提携..】
- poj 2762 Going from u to v or from v to u?
- POJ 2796 Feel Good 单调栈的应用 代码详解
- poj 1088滑雪------精简的dfs代码
- POJ - 2762(强连通模板缩点+拓扑模板)
- POJ1144 Network PASCAL代码
- poj2762 缩点+topo排序
- poj 2762 强连通分量+拓扑排序(判断图是否为单向连通)