zoukankan      html  css  js  c++  java
  • [SDOI2011]消耗战

    题目链接

    问题分析

    显然是虚树题。由于(sum kleqslant 500000),所以直接套个虚树就好了。时间经过实践是可以的

    参考代码

    #include <bits/stdc++.h>
    using namespace std;
    
    const int Maxn = 250010;
    const long long INF = 125000000010;
    const int MaxLog = 20;
    struct edge {
    	int To, Next;
    	long long c;
    	edge() : To( 0 ), Next( 0 ), c( 0 ) {} 
    	edge( int _To, int _Next, long long _c ) : To( _To ), Next( _Next ), c( _c ) {}
    };
    edge Edge[ Maxn << 1 ];
    int Start[ Maxn ], UsedEdge;
    inline void AddEdge( int x, int y, long long z ) {
    	Edge[ ++UsedEdge ] = edge( y, Start[ x ], z );
    	Start[ x ] = UsedEdge;
    	return;
    }
    int n, Dfn[ Maxn ], Deep[ Maxn ], Time;
    struct step {
    	int To;
    	long long Min;
    	step() : To( 0 ), Min( INF ) {}
    	step( int _To, long long _Min ) : To( _To ), Min( _Min ) {} 
    };
    step Step[ Maxn ][ MaxLog ];
    int m, k, H[ Maxn ];
    
    void Build( int u, int Fa, long long c ) {
    	Dfn[ u ] = ++Time;
    	Deep[ u ] = Deep[ Fa ] + 1;
    	Step[ u ][ 0 ] = step( Fa, c );
    	for( int i = 1; i < MaxLog; ++i )
    		Step[ u ][ i ] = step( Step[ Step[ u ][ i - 1 ].To ][ i - 1 ].To, 
    				min( Step[ u ][ i - 1 ].Min, Step[ Step[ u ][ i - 1 ].To ][ i - 1 ].Min ) );
    	for( int t = Start[ u ]; t; t = Edge[ t ].Next ) {
    		int v = Edge[ t ].To;
    		if( v == Fa ) continue;
    		Build( v, u, Edge[ t ].c );
    	}
    	return;
    }
    
    inline bool Cmp( int x, int y ) {
    	return Dfn[ x ] < Dfn[ y ];
    }
    
    edge Edge2[ Maxn << 1 ];
    int Start2[ Maxn ], UsedEdge2, Flag[ Maxn ], IsFlag[ Maxn ], Emmm;
    int Stack[ Maxn ];
    long long GetCost( int x, int y );
    inline void AddEdge_2( int x, int y, long long z, int flag ) {
    	if( Flag[ x ] != flag ) {
    		Start2[ x ] = 0;
    		Flag[ x ] = flag;
    	}
    	Edge2[ ++UsedEdge2 ] = edge( y, Start2[ x ], z );
    	Start2[ x ] = UsedEdge2;
    	return;
    }
    inline void AddEdge2( int x, int y, int flag ) {
    	long long z = GetCost( x, y );
    	AddEdge_2( x, y, z, flag );
    	AddEdge_2( y, x, z, flag );
    	return;
    }
    
    int GetLca( int x, int y ) {
    	if( Deep[ x ] < Deep[ y ] ) swap( x, y );
    	for( int i = MaxLog - 1; i >= 0; --i )
    		if( Deep[ Step[ x ][ i ].To ] >= Deep[ y ] )
    			x = Step[ x ][ i ].To;
    	if( x == y ) return x;
    	for( int i = MaxLog - 1; i >= 0; --i ) 
    		if( Step[ x ][ i ].To != Step[ y ][ i ].To ) {
    			x = Step[ x ][ i ].To;
    			y = Step[ y ][ i ].To;
    		}
    	return Step[ x ][ 0 ].To;
    }
    
    long long GetCost( int x, int y ) {
    	if( Deep[ x ] < Deep[ y ] ) swap( x, y );
    	long long Ans = INF;
    	for( int i = MaxLog - 1; i >= 0; --i ) 
    		if( Deep[ Step[ x ][ i ].To ] >= Deep[ y ] ) {
    			Ans = min( Ans, Step[ x ][ i ].Min );
    			x = Step[ x ][ i ].To;
    		}
    	return Ans;
    }
    
    long long Dp( int u, int Fa ) {
    	long long Ans = 0;
    	int Cnt = 0;
    	for( int t = Start2[ u ]; t; t = Edge2[ t ].Next ) {
    		int v = Edge2[ t ].To;
    		if( v == Fa ) continue;
    		++Cnt;
    		if( IsFlag[ v ] == Emmm )
    			Ans += Edge2[ t ].c;
    		else
    			Ans += min( Edge2[ t ].c, Dp( v, u ) );
    	}
    	if( Cnt ) return Ans; else return INF;
    }
    
    int main() {
    	scanf( "%d", &n );
    	for( int i = 1; i < n; ++i ) {
    		int x, y; long long z;
    		scanf( "%d%d%lld", &x, &y, &z );
    		AddEdge( x, y, z );
    		AddEdge( y, x, z );
    	}
    	Build( 1, 1, INF );
    	scanf( "%d", &m );
    	for( int i = 1; i <= m; ++i ) {
    		scanf( "%d", &k );
    		for( int j = 1; j <= k; ++j ) scanf( "%d", &H[ j ] );
    		sort( H + 1, H + k + 1, Cmp );
    		for( int j = 1; j <= k; ++j ) IsFlag[ H[ j ] ] = i;
    		Emmm = i;
    		UsedEdge2 = 0;
    		Stack[ 0 ] = 1; Stack[ 1 ] = 1;
    		for( int j = 1; j <= k; ++j ) {
    			int Lca = GetLca( Stack[ Stack[ 0 ] ], H[ j ] );
    			if( Deep[ Lca ] == Deep[ Stack[ Stack[ 0 ] ] ] ) {
    				Stack[ ++Stack[ 0 ] ] = H[ j ];
    			}
    			else {
    				while( Deep[ Lca ] < Deep[ Stack[ Stack[ 0 ] - 1 ] ] ) {
    					AddEdge2( Stack[ Stack[ 0 ] ], Stack[ Stack[ 0 ] - 1 ], i );
    					--Stack[ 0 ];
    				}
    				if( Deep[ Lca ] == Deep[ Stack[ Stack[ 0 ] - 1 ] ] ) {
    					AddEdge2( Stack[ Stack[ 0 ] ], Stack[ Stack[ 0 ] - 1 ], i );
    					--Stack[ 0 ];
    					Stack[ ++Stack[ 0 ] ] = H[ j ];
    				} else {
    					AddEdge2( Stack[ Stack[ 0 ] ], Lca, i );
    					--Stack[ 0 ];
    					Stack[ ++Stack[ 0 ] ] = Lca;
    					Stack[ ++Stack[ 0 ] ] = H[ j ];
    				}
    			}
    		}
    		while( Stack[ 0 ] >= 2 ) {
    			AddEdge2( Stack[ Stack[ 0 ] ], Stack[ Stack[ 0 ] - 1 ], i );
    			--Stack[ 0 ];
    		}
    		printf( "%lld
    ", Dp( 1, 0 ) );
    	}
    	return 0;
    }
    
  • 相关阅读:
    20210603
    20210602
    20210601
    20210531-已编辑
    2021053101
    操作系统笔记(一)
    尘埃落定,扬帆起航
    RTL级低功耗设计
    关于毛刺
    电路级拾珍
  • 原文地址:https://www.cnblogs.com/chy-2003/p/11594216.html
Copyright © 2011-2022 走看看