大家都很强, 可与之共勉 。
填一个坑,不然写了都不记得去哪儿找。
一个支配树的板子,看你们都用vector没有O2应该会被卡常数。
所以研究了一下邻接链表封装。
支配树的dom一定要开两倍,因为建树的时候也要加边23333
# define N 50010
# define M 100010
struct edge {
int to ; edge* nxt ;
} ;
struct Graph {
edge g [M << 1] ;
edge *head [N] ;
Graph ( ) { memset ( head, 0, sizeof head ) ; }
inline void add_edge ( int u, int v ) {
static edge* NewEdge ( g ) ;
*( ++ NewEdge ) = ( edge ) { v, head [u] } ; head [u] = NewEdge ;
}
inline edge*& operator [] ( const int u ) { return head [u] ; }
} ;
namespace pbds {
inline bool cmp ( const int&, const int& ) ;
struct DominatorTree {
Graph cur, rev ;
int ufs [N], val [N] ; // Union-Find-Set
int fa [N], dfn [N], id [N], idx ; // father on Dfs Tree, Dfs order, Dfs id ;
int sdom [N], idom [N] ; // half Dominate point, nearest Dominate point
Graph dom ; // save v that sdom [v] is u, at last it is Dominate Tree ;
inline void add_edge ( int u, int v ) {
cur.add_edge ( u, v ), rev.add_edge ( v, u ) ;
}
inline void dfs ( int u ) {
id [dfn [u] = ++ idx] = u ;
for ( edge* it = cur [u] ; it ; it = it -> nxt ) {
if ( ! dfn [it -> to] ) {
fa [it -> to] = u ;
dfs ( it -> to ) ;
}
}
}
inline int findfa ( int x ) {
if ( x == ufs [x] ) return x ;
int y = findfa ( ufs [x] ) ;
if ( cmp ( sdom [val [ufs [x]]], sdom [val [x]] ) ) val [x] = val [ufs [x]] ;
return ufs [x] = y ;
}
inline void build ( const int s, const int n ) {
for ( register int i = 1 ; i <= n ; ++ i ) ufs [i] = val [i] = sdom [i] = i ;
dfs ( s ) ;
for ( register int i = idx, u ; u = id [i], i > 1 ; -- i ) {
for ( edge* it = rev [u] ; it ; it = it -> nxt )
if ( dfn [it -> to] ) {
findfa ( it -> to ) ;
sdom [u] = std :: min ( sdom [u], sdom [val [it -> to]], cmp ) ;
}
dom.add_edge ( sdom [u], u ) ;
register int x = ( ufs [u] = fa [u] ) ;
for ( edge* it = dom [x] ; it ; it = it -> nxt ) {
findfa ( it -> to ) ;
idom [it -> to] = cmp ( sdom [val [it -> to]], fa [u]) ? val [it -> to] : fa [u] ;
}
dom [x] = 0 ;
}
for ( register int i = 2, u ; u = id [i], i <= idx ; ++ i ) {
( idom [u] ^ sdom [u] ) ? idom [u] = idom [idom [u]] : 0 ;
dom.add_edge ( idom [u], u ) ;
}
}
} T ;
inline bool cmp ( const int& u, const int& v ) { return T.dfn [u] < T.dfn [v] ; }
}
# undef N
# undef M