【HDU】5420 Victor and Proposition【SCC+線段樹】

題目鏈接:【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 ;
}
發佈了718 篇原創文章 · 獲贊 37 · 訪問量 64萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章