【BZOJ】2286: [Sdoi2011消耗战【虚树DP】

来源:互联网 发布:北京seo排名 编辑:程序博客网 时间:2024/05/19 18:38

传送门:【BZOJ】2286: [Sdoi2011消耗战


my code:

#include <stdio.h>#include <string.h>#include <algorithm>using namespace std ;typedef long long LL ;#define rep( i , a , b ) for ( int i = ( a ) ; i <  ( b ) ; ++ i )#define For( i , a , b ) for ( int i = ( a ) ; i <= ( b ) ; ++ i )#define rev( i , a , b ) for ( int i = ( a ) ; i >= ( b ) ; -- i )#define clrs( a , x , sizes ) memset ( a , x , sizeof ( a[0] ) * ( sizes + 1 ) )#define clr( a , x ) memset ( a , x , sizeof a )const int MAXN = 250005 ;const int MAXE = 500005 ;const int LOG = 20 ;const int INF = 0x3f3f3f3f ;const LL oo = 1e18 ;struct Edge {int v , c , n ;Edge () {}Edge ( int v , int c , int n ) : v ( v ) , c ( c ) , n ( n ) {}} ;Edge preE[MAXE] ;Edge E[MAXE] ;int preH[MAXN] , precntE ;int H[MAXN] , cntE ;int vis[MAXN] , Time ;int minv[MAXN][LOG] ;int S[MAXN] , top ;int f[MAXN][LOG] ;int tree[MAXN] ;int idx[MAXN] ;int dfs_clock ;int dep[MAXN] ;int ask[MAXN] ;int n , m ;void init () {precntE = 0 ;dfs_clock = 0 ;clrs ( preH , -1 , n ) ;}void preaddedge ( int u , int v , int c ) {preE[precntE] = Edge ( v , c , preH[u] ) ;preH[u] = precntE ++ ;}void addedge ( int u , int v , int c ) {if ( vis[u] != Time ) {vis[u] = Time ;H[u] = -1 ;}E[cntE] = Edge ( v , c , H[u] ) ;H[u] = cntE ++ ;}void dfs ( int u ) {idx[u] = ++ dfs_clock ;for ( int i = preH[u] ; ~i ; i = preE[i].n ) {int v = preE[i].v ;if ( v == f[u][0] ) continue ;dep[v] = dep[u] + 1 ;f[v][0] = u ;minv[v][0] = preE[i].c ;rep ( j , 1 , LOG ) {f[v][j] = f[f[v][j - 1]][j - 1] ;minv[v][j] = min ( minv[v][j - 1] , minv[f[v][j - 1]][j - 1] ) ;}dfs ( v ) ;}}bool cmp ( const int& x , const int& y ) {return idx[x] < idx[y] ;}int get_lca ( int x , int y ) {if ( dep[x] < dep[y] ) swap ( x , y ) ;rev ( i , LOG - 1 , 0 ) if ( dep[x] - ( 1 << i ) >= dep[y] ) x = f[x][i] ;if ( x == y ) return x ;rev ( i , LOG - 1 , 0 ) if ( f[x][i] != f[y][i] ) {x = f[x][i] ;y = f[y][i] ;}return f[x][0] ;}int get_min ( int x , int y ) {int res = INF ;if ( dep[x] < dep[y] ) swap ( x , y ) ;rev ( i , LOG - 1 , 0 ) if ( dep[x] - ( 1 << i ) >= dep[y] ) {res = min ( res , minv[x][i] ) ;x = f[x][i] ;}return res ;}LL get_ans ( int u , LL dp = 0 ) {for ( int i = H[u] ; ~i ; i = E[i].n ) {if ( ask[E[i].v] == Time ) dp += E[i].c ;else dp += min ( get_ans ( E[i].v ) , ( LL ) E[i].c ) ;}return dp ;}void deal () {int cnt ;top = 0 ;++ Time ;cntE = 0 ;scanf ( "%d" , &cnt ) ;rep ( i , 0 , cnt ) {scanf ( "%d" , &tree[i] ) ;ask[tree[i]] = Time ;}sort ( tree , tree + cnt , cmp ) ;if ( tree[0] == 1 ) S[++ top] = tree[0] ;else S[++ top] = 1 ;rep ( i , tree[0] == 1 , cnt ) {int t = tree[i] , lca = get_lca ( S[top] , t ) ;while ( top && dep[S[top]] > dep[lca] ) {if ( dep[S[top - 1]] <= dep[lca] ) {int now = S[top --] ;addedge ( lca , now , get_min ( now , lca ) ) ;break ;}addedge ( S[top - 1] , S[top] , get_min ( S[top] , S[top - 1] ) ) ;-- top ;}if ( S[top] != lca ) S[++ top] = lca ;S[++ top] = t ;}while ( top ) {addedge ( S[top - 1] , S[top] , get_min ( S[top] , S[top - 1] ) ) ;-- top ;}LL dp = get_ans ( 1 ) ;printf ( "%lld\n" , dp ) ;}void solve () {int u , v , c ;init () ;rep ( i , 1 , n ) {scanf ( "%d%d%d" , &u , &v , &c ) ;preaddedge ( u , v , c ) ;preaddedge ( v , u , c ) ;}dfs ( 1 ) ;scanf ( "%d" , &m ) ;rep ( i , 0 , m ) deal () ;}int main () {Time = 0 ;clr ( vis , 0 ) ;clr ( ask , 0 ) ;while ( ~scanf ( "%d" , &n ) ) solve () ;return 0 ;}


0 0
原创粉丝点击