Sicily 4431. 有向图边的分类

来源:互联网 发布:沈阳网络营销黑马网络 编辑:程序博客网 时间:2024/05/22 06:43

有向图边的分类……什么来的,完全没概念。上网查了下,可知:
1. 树枝,是深度优先森林Gπ中的边,如果结点v是在探寻边(u,v)时第一次被发现,那么边(u,v)就是一个树枝。
2. 反向边,是深度优先树中连结结点u到它的祖先v的那些边,环也被认为是反向边。
3. 正向边,是指深度优先树中连接顶点u到它的后裔的非树枝的边。
4. 交叉边,是指所有其他类型的边,它们可以连结同一棵深度优先树中的两个结点,
只要一结点不是另一结点的祖先,也可以连结分属两棵深度优先树的结点。
(http://www.ahhf45.com/info/data_structures_and_algorithms/algorithm/commonalg/graph/traversal/dfs.htm)
然后就利用这些特点,使用深搜来解决。树枝和反向边都很好区分,前者是发现新节点的边,后者是回溯前节点的边。但关键在于区分有边相连的两个节点是否具有前后裔的关系,这是区分正向边和交叉边的重要依据。而我是用发现先后来进行判断的:在排除树枝和反向边后,对于边(u,v),若u先被发现,则这条边是正向边;否则,就是交叉边。
另:写代码还是比较麻烦,我的代码就有近1500字节,但在查看Status时,发现居然有200多字节的!发现是熟人后,便去求代码,然后被告知:这道题的测试数据只有样例给出的那个,直接把Sample Output输出就可以AC了……

Run Time: 0sec

Run Memory: 356KB

Code length: 1371Bytes

Submit Time: 2011-12-27 11:26:42

// Problem#: 4431// Submission#: 1136604// The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License// URI: http://creativecommons.org/licenses/by-nc-sa/3.0/// All Copyright reserved by Informatic Lab of Sun Yat-sen University#include <cstdio>#include <cstring>using namespace std;int n, m, k;int u, v;int time;bool edge[ 101 ][ 101 ];int visited[ 101 ];int find[ 101 ];int kind[ 101 ][ 101 ];void DFS( int i ) {    time++;    for ( int j = 1; j <= n; j++ ) {        if ( edge[ i ][ j ] ) {            if ( visited[ j ] == 0 ) {                find[ j ] = time;                visited[ j ] = 1;                kind[ i ][ j ] = 1;                DFS( j );            }            else if ( visited[ j ] == 1 )                kind[ i ][ j ] = 3;            else if ( find[ i ] < find[ j ] )                    kind[ i ][ j ] = 2;        }    }    visited[ i ] = 2;    time++;}int main(){    char *s[ 4 ] = { "Cross Edge", "Tree Edge", "Down Edge", "Back Edge" };    memset( edge, false, sizeof( edge ) );    memset( visited, 0, sizeof( visited ) );    memset( kind, 0, sizeof( kind ) );    scanf( "%d%d", &n, &m );    while ( m-- ) {        scanf( "%d%d", &u, &v );        edge[ u ][ v ] = true;    }    time = 1;    for ( int i = 1; i <= n; i++ ) {        if ( visited[ i ] == 0 ) {            find[ i ] = time;            visited[ i ] = 1;            DFS( i );        }    }    scanf( "%d", &k );    while ( k-- ) {        scanf( "%d%d", &u, &v );        printf( "edge (%d,%d) is %s\n", u, v, s[ kind[ u ][ v ] ] );    }    return 0;}