GCJ 2016 R1A pC. BFFs ( Graph Adhoc )
Dashboard - Round 1A 2016 - Google Code Jam
There are two possible ways to form a maximum cycle:
1. Sum up for each pair ( u, v ) that share bidirectional edges, length of chain that starts with u, and v, such like f[ f[ .. f[ v ] ] ] <- f[ .. f[ v ] ] .. <- v <-> u -> f[ u ] .., where a directional arrow from x -> y shows that having x, y will be considered valid to exist next to x.
2. Maximum length of a directed cycle.
#include <bits/stdc++.h> using namespace std; const int MAXN = 1e3 + 3; int n; int f[ MAXN ]; int maxLenDirectedCycle(){ int res = 0; vector< int > depth( n + 1 ); for( int u = 1; u <= n; ++u ){ fill( depth.begin(), depth.end(), -1 ); int cur = u; int cnt = 0; while( true ){ depth[ cur ] = cnt++; if( depth[ f[ cur ] ] != -1 ){ cnt = depth[ cur ] - depth[ f[ cur ] ] + 1; break; } cur = f[ cur ]; } res = max( res, cnt ); } return res; } vector< int > G[ MAXN ]; // G[ u ] stores people that need u int vis[ MAXN ]; int getMaxLen( int u, int fa ){ vis[ u ] = 1; int res = 1; for( int v : G[ u ] ){ if( v == fa ) continue; if( vis[ v ] ) continue; res = max( res, getMaxLen( v, u ) + 1 ); } return res; } int maxLenTwoChain(){ int res = 0; memset( vis, 0, sizeof( vis ) ); for( int i = 1; i <= n; ++i ) G[ i ].clear(); for( int u = 1; u <= n; ++u ) G[ f[ u ] ].push_back( u ); for( int u = 1; u <= n; ++u ) if( u == f[ f[ u ] ] ){ if( vis[ u ] ) continue; res += getMaxLen( u, f[ u ] ) + getMaxLen( f[ u ], u ); } return res; } void solve(){ int ans1 = maxLenDirectedCycle(); int ans2 = maxLenTwoChain(); printf( "%d\n", max( ans1, ans2 ) ); } int main(){ int T; scanf( "%d", &T ); for( int kase = 1; kase <= T; ++kase ){ printf( "Case #%d: ", kase ); scanf( "%d", &n ); for( int i = 1; i <= n; ++i ) scanf( "%d", f + i ); solve(); } return 0; }