[NOIP2012]疫情控制
来源:互联网 发布:牛仔衬衫 知乎 编辑:程序博客网 时间:2024/05/02 01:09
题目链接:CodeVS1218
题目大意
大小为
分析
1. 对于所有的军队,越往上,显然能封锁的节点就越多;时间越多,能往上跑的距离就越多;所以二分时间。
2. 有一些军队,可以跨过根节点而控制根节点的其他子节点( 以下简称为子节点 )。
3. 对于不能跨根节点的军队( 包括不能到根和刚好能到根 ),直接在停止处标记;而那些可以跨根的军队,要记录起来( 记为
4. 对于子节点,其是否需要从跟节点调用一支军队来控制可以通过一次dfs搜索判断;需要军队的记录下来( 记为
5. 先把
6. 然而,当前的
6.5 本人当时用了一个非常低效的匹配方法,导致无限T,因此开了一些优化,比如倍增(其实不倍增并不会慢多少)。
上代码
#include <cstdio>#include <cstring>#include <algorithm>#include <vector>using namespace std ;const int N = 5e4 + 10 ;const int M = 30 + 10 ;int n, m, tot ;struct node_edge { int to, val ;} ;vector < node_edge > edge[ N ] ;struct node_army { // 记录军队 int plc, time, nown ; // 起始位置,剩余时限,目前位置 // 其中plc是不变的,而time和nown是变化的} army[ N ] ;// dfs一棵树// fa[i][j]表示i的 2^j 祖先,所以fa[i][0]即为i的父亲int fa[ N ][ M ], dist[ N ] ; void dfs( int a , int b ) { fa[ a ][ 0 ] = b ; for ( int i = 0 ; i < edge[ a ].size() ; i ++ ) { int node = edge[ a ][ i ].to ; if ( node == b ) continue ; dist[ node ] = dist[ a ] + edge[ a ][ i ].val ; dfs( node , a ) ; }}// 为了优化,我连倍增都用了,当时无限T的心情可以脑补// 树上倍增inline void calc_fa() { for ( int j = 1 ; ; j ++ ) { int flag = false ; for ( int i = 1 ; i <= n ; i ++ ) { int node = fa[ i ][ j - 1 ] ; if ( !fa[ node ][ j - 1 ] ) continue ; flag = true ; fa[ i ][ j ] = fa[ node ][ j - 1 ] ; } if ( !flag ) return ; }}// 读入优化,说多了都是泪inline void get_num( int &a ) { char ch ; while ( ch = getchar(), ch >= '0' && ch <= '9' ) a = a * 10 + ch - '0' ; return ;}inline void init() { scanf( "%d", &n ) ; getchar() ; for ( int i = 1 ; i < n ; i ++ ) { int a = 0, b = 0, c = 0 ; get_num( a ), get_num( b ), get_num( c ) ; edge[ a ].push_back( (node_edge){ b , c } ) ; edge[ b ].push_back( (node_edge){ a , c } ) ; tot += c ; } dfs( 1 , 0 ), calc_fa() ; scanf( "%d", &m ) ; getchar() ; for ( int i = 1 ; i <= m ; i ++ ) get_num( army[ i ].plc ) ;}bool book[ N ] ; // 封锁标记int lx, ly ;struct node_xxyy { int from, val ; // 对X为军队的来源和剩余时间 // 对Y为子节点和距离 inline bool operator < ( const node_xxyy a ) const { return val < a.val ; }} x[ N ], y[ N ] ;inline void go_up( int a ) { int node = army[ a ].nown ; while ( fa[ node ][ 0 ] != 1 ) { int k = 0 ; while ( fa[ node ][ k ] != 1 && fa[ node ][ k ] != 0 ) { if ( dist[ node ] - dist[ fa[ node ][ k ] ] <= army[ a ].time ) k ++ ; else break ; } if ( k == 0 ) { book[ army[ a ].nown = node ] = true ; return ; } else { army[ a ].time -= dist[ node ] - dist[ fa[ node ][ k - 1 ] ] ; army[ a ].nown = node = fa[ node ][ k - 1 ] ; } } if ( army[ a ].time <= dist[ army[ a ].nown ] ) book[ army[ a ].nown ] = true ; return ;}bool check( int a ) { if ( book[ a ] ) return true ; for ( int i = 0 ; i < edge[ a ].size() ; i ++ ) { int node = edge[ a ][ i ].to ; if ( node == fa[ a ][ 0 ] ) continue ; if ( !check( node ) ) return false ; } if ( edge[ a ].size() > 1 ) { book[ a ] = true ; return true ; //优化之一 } else return false ;}inline bool judge( int valn ) { for ( int i = 1 ; i <= m ; i ++ ) army[ i ].time = valn, army[ i ].nown = army[ i ].plc ; for ( int i = 1 ; i <= m ; i ++ ) { go_up( i ) ; if ( army[ i ].time > dist[ army[ i ].nown ] ) // 说明可以越根 x[ ++ lx ] = (node_xxyy){ army[ i ].nown , army[ i ].time - dist[ army[ i ].nown ] } ; } for ( int i = 0 ; i < edge[ 1 ].size() ; i ++ ) if ( !check( edge[ 1 ][ i ].to ) ) y[ ++ ly ] = (node_xxyy){ edge[ 1 ][ i ].to , dist[ edge[ 1 ][ i ].to ] } ; if ( lx < ly ) return false ; // 剪枝 sort( x + 1 , x + lx + 1 ) ; sort( y + 1 , y + ly + 1 ) ; int mark = 1 ; for ( int i = 1 ; i <= lx ; i ++ ) { //我T就是T在这个匹配,我原来的版本太low了:在Y中upper_bound() if ( !book[ x[ i ].from ] ) { book[ x[ i ].from ] = true ; continue ; } else { while ( book[ y[ mark ].from ] && mark < ly ) mark ++ ; if ( x[ i ].val >= y[ mark ].val ) { book[ y[ mark ].from ] = true ; mark ++ ; } } } for ( int i = 1 ; i <= ly ; i ++ ) if ( !check( y[ i ].from ) ) return false ; return true ;}inline int figure() { if ( m < edge[ 1 ].size() ) return -1 ; // 唯一无法封锁的情况 int ans ; int l = 1, r = tot, mid ; while ( l <= r ) { lx = ly = 0 ; memset( book , 0 , sizeof( book ) ) ; mid = ( l + r ) >> 1 ; if ( judge( mid ) ) r = mid - 1, ans = mid ; else l = mid + 1 ; } return ans ;}int main() { init() ; printf( "%d\n", figure() ) ; return 0 ;}
以上
0 0
- 【思维】NOIP2012疫情控制
- NOIP2012 疫情控制
- noip2012疫情控制
- codevs1218: [NOIP2012]疫情控制
- 【NOIP2012】Day2T3 疫情控制
- NOIP2012 疫情控制
- [NOIP2012]疫情控制
- noip2012:疫情控制
- NOIp2012疫情控制
- 【NOIP2012】疫情控制
- [NOIP2012]疫情控制
- 【NOIP2012】疫情控制
- [noip2012]疫情控制
- NOIP2012 day2 T3 疫情控制
- 【NOIP2012提高组】疫情控制
- 【NOIP2012提高组】疫情控制
- 【NOIP2012】洛谷1084 疫情控制
- noip2012 day2 T3 疫情控制
- iOS JPUSH接入的详细讲解
- Android 6.0之后获取sd卡信息的方法
- Unable to start activity ComponentInfo,请教如何解决?
- React Native 之 Handling Text Input
- FilterEncode
- [NOIP2012]疫情控制
- MyEclipse快捷键大全
- NOIp2015 提高组 信息传递
- div/css居中页面不变尺寸
- 最近的一些感悟
- X-code -- xcode8之Memory Graph实战解决闭包引用循环问题
- SendMessage向编辑框发送消息
- Trafodion 创建表
- [Rosyln学习记录1]安装与配置