题目大意
给定一个
n
个点
Data Constraint
n≤7500,m≤100000
题解
因为是DAG,先考虑构出图的拓补序。
设
fi
表示第1层的点到
i
最长路为
在原图中,那么我们一条边
(u,v)
对答案的贡献就是
fu+gv+1
,现在按照拓补序依次尝试删除结点。那么当
u
已被尝试删除过,且
所以每次尝试删除
x
之前就将
数据结构维护最大值即可。注意
f,g
本身也能算贡献。
时间复杂度: O(nlogn)
SRC
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<set>
using namespace std ;
#define N 75000 + 10
#define M 100000 + 10
multiset < int > Q ;
int Node[2*M] , Next[2*M] , Head[N] , _Head[N] , tot ;
int D[N] , R[N] , f[N] , g[N] ;
int n , m , ans1 , ans2 = 0x7FFFFFFF ;
void link( int u , int v ) {
Node[++tot] = v ;
Next[tot] = Head[u] ;
Head[u] = tot ;
}
void Revlink( int u , int v ) {
Node[++tot] = v ;
Next[tot] = _Head[u] ;
_Head[u] = tot ;
}
void BFS() {
int i = 0 , j = D[0] ;
while ( i < j ) {
i ++ ;
int now = D[i] ;
for (int p = Head[now] ; p ; p = Next[p] ) {
R[Node[p]] -- ;
if ( R[Node[p]] == 0 ) D[++j] = Node[p] ;
}
}
D[0] = j ;
}
int main() {
freopen( "chronosphere.in" , "r" , stdin ) ;
freopen( "chronosphere.out" , "w" , stdout ) ;
scanf( "%d%d" , &n , &m ) ;
for (int i = 1 ; i <= m ; i ++ ) {
int u , v ;
scanf( "%d%d" , &u , &v ) ;
link( u , v ) ;
Revlink( v , u ) ;
R[v] ++ ;
}
for (int i = 1 ; i <= n ; i ++ ) if ( R[i] == 0 ) D[++D[0]] = i ;
BFS() ;
for (int i = D[0] ; i >= 1 ; i -- ) {
int now = D[i] ;
g[now] = -1 ;
for (int p = Head[now] ; p ; p = Next[p] ) {
g[now] = max( g[now] , g[Node[p]] ) ;
}
g[now] ++ ;
}
for (int i = 1 ; i <= D[0] ; i ++ ) {
int now = D[i] ;
f[now] = -1 ;
for (int p = _Head[now] ; p ; p = Next[p] ) {
f[now] = max( f[now] , f[Node[p]] ) ;
}
f[now] ++ ;
}
for (int i = 1 ; i <= n ; i ++ ) Q.insert( g[i] ) ;
for (int i = 1 ; i <= D[0] ; i ++ ) {
int now = D[i] ;
for (int p = _Head[now] ; p ; p = Next[p] )
Q.erase( Q.find(f[Node[p]] + g[now] + 1) ) ;
Q.erase( Q.find(g[now]) ) ;
multiset <int> :: iterator it = Q.end() ;
if ( it != Q.begin() ) {
it -- ;
if ( *it < ans2 ) ans1 = now , ans2 = *it ;
else if ( *it == ans2 && now < ans1 ) ans1 = now ;
}
for (int p = Head[now] ; p ; p = Next[p] )
Q.insert( f[now] + g[Node[p]] + 1 ) ;
Q.insert( f[now] ) ;
}
printf( "%d %d\n" , ans1 , ans2 ) ;
return 0 ;
}
以上.