0w1

CFR 349 D. World Tour ( Graph )

Problem - D - Codeforces
Edges are all weighted 1, so we can apply BFS for single source shortest path, for each node as source. This allows us to get all pairwise distances in O( n ^ 2 ). Since we are to find the maximum distance of path a -> b -> c -> d, like always, let us first enumerate the "bridge", which is obvious for b -> c to be. Now we will find maximum a -> b and maximum c -> d, which can be done in O( 1 ) with precomputing and sorting.

vector< int > G[ MAXN ];
int dis[ MAXN ][ MAXN ];
vector< pii > start_dis_rank[ MAXN ];
vector< pii > end_dis_rank[ MAXN ]; // paths that end with u

void solve(){
    int n, m; scanf( "%d%d", &n, &m );
    for( int i = 0; i < m; ++i ){
        int u, v; scanf( "%d%d", &u, &v );
        G[ u ].push_back( v );
    }
    memset( dis, INF, sizeof( dis ) );
    for( int i = 1; i <= n; ++i ){ // SSSP to get all pairwise distances
        queue< pii > que;
        que.push( pii( dis[ i ][ i ] = 0, i ) );
        while( !que.empty() ){
            int u = que.front().second;
            que.pop();
            for( int v : G[ u ] ){
                if( dis[ i ][ v ] > dis[ i ][ u ] + 1 )
                    dis[ i ][ v ] = dis[ i ][ u ] + 1,
                    que.push( pii( dis[ i ][ v ], v ) );
            }
        }
    }
    for( int i = 1; i <= n; ++i ){ // arrange nodes reachable from i by distance
        for( int j = 1; j <= n; ++j ) if( i != j )
            if( dis[ i ][ j ] < INF )
                start_dis_rank[ i ].push_back( pii( dis[ i ][ j ], j ) );
        sort( start_dis_rank[ i ].begin(), start_dis_rank[ i ].end(), greater< pii >() );
    }
    for( int j = 1; j <= n; ++j ){ // arrange nodes ending with j by distance
        for( int i = 1; i <= n; ++i ) if( j != i )
            if( dis[ i ][ j ] < INF )
                end_dis_rank[ j ].push_back( pii( dis[ i ][ j ], i ) );
        sort( end_dis_rank[ j ].begin(), end_dis_rank[ j ].end(), greater< pii >() );
    }
    int ans = 0;
    vector< int > chose;
    for( int b = 1; b <= n; ++b )
        for( int c = 1; c <= n; ++c ) if( b != c && dis[ b ][ c ] < INF ){ // enumerate bridge
            int amax[ 3 ], amax_idx[ 3 ] = { -1, -1, -1 }; // may use up to 3, since a != b AND a != c AND a != d
            for( int i = 0; i < 3; ++i ) if( i < end_dis_rank[ b ].size() )
                amax[ i ] = end_dis_rank[ b ][ i ].first,
                amax_idx[ i ] = end_dis_rank[ b ][ i ].second;
            int dmax[ 3 ], dmax_idx[ 3 ] = { -1, -1, -1 };
            for( int i = 0; i < 3; ++i ) if( i < start_dis_rank[ c ].size() )
                dmax[ i ] = start_dis_rank[ c ][ i ].first,
                dmax_idx[ i ] = start_dis_rank[ c ][ i ].second;
            for( int i = 0; i < 3; ++i ) if( amax_idx[ i ] != -1 && amax_idx[ i ] != c )
                for( int j = 0; j < 3; ++j ) if( dmax_idx[ j ] != -1 && dmax_idx[ j ] != b )
                    if( amax_idx[ i ] != dmax_idx[ j ] )
                        if( ans < amax[ i ] + dis[ b ][ c ] + dmax[ j ] )
                            ans = amax[ i ] + dis[ b ][ c ] + dmax[ j ],
                            chose = { amax_idx[ i ], b, c, dmax_idx[ j ] };
        }
    for( int i = 0; i < 4; ++i )
        printf( "%d%c", chose[ i ], i + 1 == 4 ? '\n' : ' ' );
}