【HDU】5420 Victor and Proposition【SCC+线段树】

来源:互联网 发布:营养配餐软件 编辑:程序博客网 时间:2024/06/06 03:35

题目链接:【HDU】5420 Victor and Proposition

#include <bits/stdc++.h>using namespace std ;typedef long long LL ;#define clr( a , x ) memset ( a , x , sizeof a )const int MAXN = 100005 ;const int MAXM = 4000005 ;const int MAXE = 20000005 ;struct Edge {    int v , n ;    Edge () {}    Edge ( int v , int n ) : v ( v ) , n ( n ) {}} E[MAXE] ;struct Node {    int l , r ;} T[MAXM] ;vector < int > G[MAXN] ;int H[MAXM] , cntE ;int root[MAXN] ;bool vis[MAXM] ;int dep[MAXN] ;int idx[MAXN] ;int dfn[MAXM] ;int low[MAXM] ;int num[MAXM] ;int scc[MAXM] ;int scc_cnt ;int dfs_idx ;int S[MAXM] ;int top ;int cur ;int n ;void init () {    top = 0 ;    cur = 1 ;    cntE = 0 ;    scc_cnt = 0 ;    dfs_idx = 0 ;    clr ( H , -1 ) ;    clr ( dfn , 0 ) ;    clr ( scc , 0 ) ;    clr ( vis , 0 ) ;}void addedge ( int u , int v ) {    E[cntE] = Edge ( v , H[u] ) ;    H[u] = cntE ++ ;}int newnode () {    T[cur].l = T[cur].r = 0 ;    return cur ++ ;}int add ( int x , int l , int r ) {    int o = newnode () ;    if ( l == r ) vis[idx[x] = o] = 1 ;    else {        int m = l + r >> 1 ;        if ( dep[x] <= m ) addedge ( o , T[o].l = add ( x , l , m ) ) ;        else addedge ( o , T[o].r = add ( x , m + 1 , r ) ) ;    }    return o ;}int merge ( int x , int y ) {    if ( !x ) return y ;    if ( !y ) return x ;    int o = newnode () ;    addedge ( o , x ) ;    addedge ( o , y ) ;    if ( T[x].l || T[y].l ) T[o].l = merge ( T[x].l , T[y].l ) ;    if ( T[x].r || T[y].r ) T[o].r = merge ( T[x].r , T[y].r ) ;    if ( T[o].l ) addedge ( o , T[o].l ) ;    if ( T[o].r ) addedge ( o , T[o].r ) ;    return o ;}int dfs ( int u ) {    root[u] = add ( u , 1 , n ) ;    for ( int i = 0 ; i < G[u].size () ; ++ i ) {        dep[G[u][i]] = dep[u] + 1 ;        root[u] = merge ( root[u] , dfs ( G[u][i] ) ) ;    }    return root[u] ;}void update ( int L , int R , int v , int o , int l , int r ) {    if ( L <= l && r <= R ) {        addedge ( v , o ) ;        return ;    }    int m = l + r >> 1 ;    if ( L <= m && T[o].l ) update ( L , R , v , T[o].l , l , m ) ;    if ( m <  R && T[o].r ) update ( L , R , v , T[o].r , m + 1 , r ) ;}int tarjan ( int u ) {    dfn[u] = low[u] = ++ dfs_idx ;    S[top ++] = u ;    for ( int i = H[u] ; ~i ; i = E[i].n ) {        int v = E[i].v ;        if ( !dfn[v] ) low[u] = min ( low[u] , tarjan ( v ) ) ;        else if ( !scc[v] ) low[u] = min ( low[u] , dfn[v] ) ;    }    if ( low[u] == dfn[u] ) {        num[++ scc_cnt] = 0 ;        do {            scc[S[-- top]] = scc_cnt ;             if ( vis[S[top]] ) ++ num[scc_cnt] ;        } while ( S[top] != u ) ;    }    return low[u] ;}void solve () {    int x , y ;    init () ;    scanf ( "%d" , &n ) ;    for ( int i = 1 ; i <= n ; ++ i ) {        G[i].clear () ;    }    for ( int i = 2 ; i <= n ; ++ i ) {        scanf ( "%d" , &x ) ;        G[x].push_back ( i ) ;    }    dep[1] = 1 ;    dfs ( 1 ) ;    for ( int i = 1 ; i <= n ; ++ i ) {        scanf ( "%d%d" , &x , &y ) ;        update ( dep[x] , min ( dep[x] + y , n ) , idx[i] , root[x] , 1 , n ) ;    }    for ( int i = 1 ; i <= n ; ++ i ) if ( !dfn[i] ) {        tarjan ( i ) ;    }    LL ans = 0 ;    for ( int i = 1 ; i <= scc_cnt ; ++ i ) {         ans += 1LL * num[i] * ( num[i] - 1 ) / 2 ;    }    printf ( "%lld\n" , ans ) ;}int main () {    int T ;    scanf ( "%d" , &T ) ;    for ( int i = 1 ; i <= T ; ++ i ) {        solve () ;    }    return 0 ;}
0 0