传送门:【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 ; }