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;
    }
    
  • 相关阅读:
    古谚、评论与论断、名篇与名言
    重读《西游记》
    重读《西游记》
    命名之法 —— 时间、季节、地点
    命名之法 —— 时间、季节、地点
    文言的理解 —— 古时的称谓、别称、别名
    文言的理解 —— 古时的称谓、别称、别名
    Oracle GoldenGate for Oracle 11g to PostgreSQL 9.2.4 Configuration
    瀑布 敏捷 文档
    POJ 1325 ZOJ 1364 最小覆盖点集
  • 原文地址:https://www.cnblogs.com/chy-2003/p/11594216.html
Copyright © 2011-2022 走看看