zoukankan      html  css  js  c++  java
  • CF613D Kingdom and its Cities

    题目链接

    问题分析

    首先看数据范围不难发现是虚树。

    但是这个DP怎么写的我这么难受……

    应该是不难的DP,(F[i][0])表示(i)不占领,(F[i][1])表示(i)占领,然后分类讨论……具体的见代码吧……

    参考程序

    #include <bits/stdc++.h>
    using namespace std;
    
    const int Maxn = 100010;
    const int INF = 1000010;
    const int MaxLog = 20;
    struct edge {
    	int Next, To;
    	edge() {}
    	edge( int _To, int _Next ) : Next( _Next ), To( _To ) {}
    };
    struct graph {
    	int Start[ Maxn ], Used;
    	edge Edge[ Maxn << 1 ];
    	int State, Flag[ Maxn ], Important[ Maxn ];
    	graph() {
    		memset( Flag, 255, sizeof( Flag ) );
    		memset( Important, 255, sizeof( Important ) );
    		Used = State = 0;
    		return;
    	}
    	inline void Set( int _State ) {
    		State = _State; Used = 0;
    		return;
    	}
    	inline void SetImportant( int u ) {
    		Important[ u ] = State;
    		return;
    	}
    	inline bool IsImportant( int u ) {
    		return Important[ u ] == State;
    	}
    	inline void AddDirectedEdge( int x, int y ) {
    		if( Flag[ x ] != State ) {
    			Flag[ x ] = State;
    			Start[ x ] = 0;
    		}
    		Edge[ ++Used ] = edge( y, Start[ x ] );
    		Start[ x ] = Used;
    		return;
    	}
    	inline void AddUndirectedEdge( int x, int y ) {
    		AddDirectedEdge( x, y );
    		AddDirectedEdge( y, x );
    		return;
    	}
    };
    graph Prime, Now;
    int n, q, k, A[ Maxn ];
    int Deep[ Maxn ], D[ Maxn ][ MaxLog ], Dfn[ Maxn ], Time;
    
    void Build( int u, int Fa ) {
    	Dfn[ u ] = ++Time;
    	Deep[ u ] = Deep[ Fa ] + 1;
    	D[ u ][ 0 ] = Fa;
    	for( int i = 1; i < MaxLog; ++i ) 
    		D[ u ][ i ] = D[ D[ u ][ i - 1 ] ][ i - 1 ];
    	for( int t = Prime.Start[ u ]; t; t = Prime.Edge[ t ].Next ) {
    		int v = Prime.Edge[ t ].To;
    		if( v == Fa ) continue;
    		Build( v, u );
    	}
    	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[ D[ x ][ i ] ] >= Deep[ y ] )
    			x = D[ x ][ i ];
    	if( x == y ) return x;
    	for( int i = MaxLog - 1; i >= 0; --i )
    		if( D[ x ][ i ] != D[ y ][ i ] ) {
    			x = D[ x ][ i ];
    			y = D[ y ][ i ];
    		}
    	return D[ x ][ 0 ];
    }
    
    int Stack[ Maxn ];
    
    bool Cmp( int x, int y ) {
    	return Dfn[ x ] < Dfn[ y ];
    }
    
    int F[ Maxn ][ 2 ];
    
    void Dp( int u, int Fa ) {
    	for( int t = Now.Start[ u ]; t; t = Now.Edge[ t ].Next ) {
    		int v = Now.Edge[ t ].To;
    		if( v == Fa ) continue;
    		Dp( v, u );
    	}
    	if( Now.IsImportant( u ) ) {
    		F[ u ][ 0 ] = INF;
    		F[ u ][ 1 ] = 0;
    		for( int t = Now.Start[ u ]; t; t = Now.Edge[ t ].Next ) {
    			int v = Now.Edge[ t ].To;
    			if( v == Fa ) continue;
    			if( Deep[ v ] - Deep[ u ] > 1 )
    				F[ u ][ 1 ] += min( F[ v ][ 0 ], F[ v ][ 1 ] + 1 );
    			else 
    				F[ u ][ 1 ] += F[ v ][ 0 ];
    		}
    	} else {
    		F[ u ][ 0 ] = 0;
    		int Max = 0;
    		for( int t = Now.Start[ u ]; t; t = Now.Edge[ t ].Next ) {
    			int v = Now.Edge[ t ].To;
    			if( v == Fa ) continue;
    			if( Deep[ v ] - Deep[ u ] > 1 ) {
    				F[ u ][ 0 ] += min( F[ v ][ 0 ], F[ v ][ 1 ] + 1 );
    				Max = max( Max, min( F[ v ][ 0 ], F[ v ][ 1 ] + 1 ) - F[ v ][ 1 ] );
    			} else {
    				F[ u ][ 0 ] += F[ v ][ 0 ];
    				Max = max( Max, F[ v ][ 0 ] - F[ v ][ 1 ] );
    			}
    		}
    		F[ u ][ 1 ] = F[ u ][ 0 ] - Max;
    		int T = 1;
    		for( int t = Now.Start[ u ]; t; t = Now.Edge[ t ].Next ) {
    			int v = Now.Edge[ t ].To;
    			if( v == Fa ) continue;
    			T += min( F[ v ][ 0 ], F[ v ][ 1 ] );
    		}
    		F[ u ][ 0 ] = min( F[ u ][ 0 ], T );
    	}
    	return;
    }
    
    int main() {
    	Prime.Set( 0 );
    	scanf( "%d", &n );
    	for( int i = 1; i < n; ++i ) {
    		int x, y;
    		scanf( "%d%d", &x, &y );
    		Prime.AddUndirectedEdge( x, y );
    	}
    	Build( 1, 0 );
    	scanf( "%d", &q );
    	for( int i = 1; i <= q; ++i ) {
    		Now.Set( i );
    		scanf( "%d", &k );
    		for( int j = 1; j <= k; ++j ) scanf( "%d", &A[ j ] );
    		for( int j = 1; j <= k; ++j ) Now.SetImportant( A[ j ] );
    		sort( A + 1, A + k + 1, Cmp );
    		Stack[ 0 ] = Stack[ 1 ] = 1;
    		for( int j = 1; j <= k; ++j ) {
    			if( j == 1 && A[ 1 ] == 1 ) continue;
    			int Lca = GetLca( Stack[ Stack[ 0 ] ], A[ j ] );
    			if( Deep[ Lca ] == Deep[ Stack[ Stack[ 0 ] ] ] )
    				Stack[ ++Stack[ 0 ] ] = A[ j ];
    			else {
    				while( Deep[ Lca ] < Deep[ Stack[ Stack[ 0 ] - 1 ] ] ) {
    					Now.AddUndirectedEdge( Stack[ Stack[ 0 ] ], Stack[ Stack[ 0 ] - 1 ] );
    					--Stack[ 0 ];
    				}
    				if( Deep[ Lca ] == Deep[ Stack[ Stack[ 0 ] - 1 ] ] ) {
    					Now.AddUndirectedEdge( Stack[ Stack[ 0 ] ], Stack[ Stack[ 0 ] - 1 ] );
    					--Stack[ 0 ];
    					Stack[ ++Stack[ 0 ] ] = A[ j ];
    				} else {
    					Now.AddUndirectedEdge( Stack[ Stack[ 0 ] ], Lca );
    					--Stack[ 0 ];
    					Stack[ ++Stack[ 0 ] ] = Lca;
    					Stack[ ++Stack[ 0 ] ] = A[ j ];
    				}
    			}
    		}
    		while( Stack[ 0 ] > 1 ) {
    			Now.AddUndirectedEdge( Stack[ Stack[ 0 ] ], Stack[ Stack[ 0 ] - 1 ] );
    			--Stack[ 0 ];
    		}
    		Dp( 1, 0 );
    		int Ans = min( F[ 1 ][ 0 ], F[ 1 ][ 1 ] );
    		if( Ans > n ) printf( "-1
    " ); else printf( "%d
    ", Ans );
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    开始使用ACE工作
    I AM NOTHING vs I AM SOMETHING
    After you have run the GIS Server Post Install
    李开复的勇气论
    爱到底是什么?
    办公室交际不能碰触的“地雷”
    近日比较忙顾不上写随笔了
    什么是爱情?什么是婚姻?
    给自己科普一下SOA、AOP、ORM
    成功者需要具备的素质
  • 原文地址:https://www.cnblogs.com/chy-2003/p/11608664.html
Copyright © 2011-2022 走看看