#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<stack>
using namespace std ;
const int maxn = 111111 ;
vector<int> g[maxn] ;
vector<int> vec[maxn] ;
int pre[maxn] , lowlink[maxn] , sccno[maxn] , dfs_clock , scc_cnt , val[maxn] , du[maxn] ;
stack<int> S;
void dfs ( int u ) {
pre[u] = lowlink[u] = ++ dfs_clock ;
S.push ( u ) ;
for ( int i = 0 ; i < g[u].size () ; i ++ ) {
int v = g[u][i] ;
if ( !pre[v] ) {
dfs ( v ) ;
lowlink[u] = min ( lowlink[u] , lowlink[v] ) ;
} else if ( !sccno[v] ) {
lowlink[u] = min ( lowlink[u] , pre[v] ) ;
}
}
if ( lowlink[u] == pre[u] ) {
scc_cnt ++ ;
for ( ; ; ) {
int x = S.top () ; S.pop () ;
sccno[x] = scc_cnt ;
if ( x == u ) break ;
}
}
}
void find_scc ( int n ) {
dfs_clock = scc_cnt = 0 ;
while ( !S.empty() ) S.pop () ;
memset ( sccno , 0 , sizeof ( sccno ) ) ;
memset ( pre , 0 , sizeof ( pre ) ) ;
for ( int i = 1 ; i <= n ; i ++ )
if ( !pre[i] ) dfs ( i ) ;
// for ( int i = 1 ; i <= n ; i ++ )
// printf ( "%d " , sccno[i] ) ;
// puts ( "" ) ;
}
void new_graph ( int n ) {
memset ( du , 0 , sizeof ( du ) ) ;
memset ( val , 0 , sizeof ( val ) ) ;
for ( int i = 1 ; i <= n ; i ++ ) {
val[sccno[i]] ++ ;
}
for ( int i = 1 ; i <= n ; i ++ ) vec[i].clear () ;
for ( int i = 1 ; i <= n ; i ++ ) {
for ( int j = 0 ; j < g[i].size () ; j ++ ) {
int u = sccno[i] ;
int v = sccno[g[i][j]] ;
// printf ( "i = %d , g = %d\n" , i , g[i][j] ) ;
// printf ( "u = %d , v = %d\n" , u , v ) ;
if ( u != v ) {
vec[u].push_back ( v ) , du[v] ++ ;
// printf () ;
}
}
}
// printf ( " scccnt %d\n" , scc_cnt ) ;
// for ( int i = 1 ; i <= scc_cnt ; i ++ ) {
// for ( int j = 0 ; j < vec[i].size () ; j ++ )
// printf ( "fuck %d %d\n" , i , vec[i][j] ) ;
// }
}
int dp[maxn] ;
int get_ans ( int u ) {
if ( dp[u] ) return dp[u] ;
int mx = 0 ;
for ( int i = 0 ; i < vec[u].size () ; i ++ ) {
int v = vec[u][i] ;
mx = max ( mx , get_ans ( v ) ) ;
}
dp[u] = mx + val[u] ;
return dp[u] ;
}
int main () {
int n , m ;
while ( scanf ( "%d%d" , &n , &m ) != EOF ) {
memset ( dp , 0 , sizeof ( dp ) ) ;
for ( int i = 1 ; i <= n ; i ++ ) g[i].clear () ;
while ( m -- ) {
int a , b ;
scanf ( "%d%d" , &a , &b ) ;
g[a].push_back ( b ) ;
}
find_scc ( n ) ;
new_graph ( n ) ;
int ans = 0 ;
for ( int i = 1 ; i <= scc_cnt ; i ++ ) {
if ( du[i] == 0 ) {
// printf ( "i = %d , fuck = %d\n" , i , get_ans (i) );
ans = max ( ans , get_ans ( i ) ) ;
}
}
printf ( "%d\n" , ans ) ;
}
return 0 ;
}
/*
3 3
1 2
2 3
3 1
16 17
14 16
16 15
15 14
5 1
1 2
2 6
6 13
6 3
13 3
3 2
3 4
4 1
5 7
7 8
8 9
9 10
10 11
*/
zoj 3795 Grouping(强连通缩点)
最新推荐文章于 2018-08-07 16:22:37 发布