BZOJ 1576: [Usaco2009 Jan]安全路经Travel( 树链剖分 )
树链剖分...略麻烦...
--------------------------------------------------------------------------------
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<iostream>
#define rep( i , n ) for( int i = 0 ; i < n ; ++i )
#define clr( x , c ) memset( x , c , sizeof( x ) )
#define REP( x ) for( edge* e = head[ x ] ; e ; e = e -> next )
#define L( x ) ( ( x ) << 1 )
#define R( x ) ( L( x ) ^ 1 )
#define M( l , r ) ( ( l + r ) >> 1 )
#define LC L( x ) , l , m
#define RC R( x ) , m + 1 , r
#define X x , l , r
#define XX int x , int l , int r
#define all 1 , 1 , n
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxm = 200000 + 5;
const int maxn = 100000 + 5;
const int maxnode = 270000;
int n;
struct edge {
int to , dist;
bool is;
edge* next;
edge() {
is = false;
}
};
edge* pt , EDGE[ maxm << 1 ];
edge* head[ maxn ];
void edge_init() {
pt = EDGE;
clr( head , 0 );
}
void add( int u , int v , int d ) {
pt -> to = v;
pt -> dist = d;
pt -> next = head[ u ];
head[ u ] = pt++;
}
#define add_edge( u , v , d ) add( u , v , d ) , add( v , u , d )
struct node {
int x , d;
bool operator < ( const node &o ) const {
return d > o.d;
}
};
priority_queue< node > Q;
int d[ maxn ];
void dijkstra() {
clr( d , inf );
d[ 0 ] = 0;
Q.push( ( node ) { 0 , 0 } );
while( ! Q.empty() ) {
node o = Q.top();
Q.pop();
int x = o.x , dist = o.d;
if( d[ x ] != dist ) continue;
REP( x ) {
int to = e -> to;
if( d[ to ] > dist + e -> dist ) {
d[ to ] = dist + e -> dist;
Q.push( ( node ) { to , d[ to ] } );
}
}
}
}
void build_tree() {
rep( x , n ) {
int dist = d[ x ];
REP( x ) {
int to = e -> to;
if( e -> dist + d[ x ] == d[ to ] )
e -> is = true;
}
}
}
int top[ maxn ] , id[ maxn ] , son[ maxn ] , fa[ maxn ], id_cnt = 0;
int size[ maxn ] , dep[ maxn ];
void dfs( int x ) {
size[ x ] = 1;
son[ x ] = -1;
REP( x ) {
int to = e -> to;
if( to == fa[ x ] || ! e -> is ) continue;
fa[ to ] = x;
dep[ to ] = dep[ x ] + 1;
dfs( to );
size[ x ] += size[ to ];
if( son[ x ] == -1 || size[ to ] > size[ son[ x ] ] )
son[ x ] = to;
}
}
int TOP;
void DFS( int x ) {
top[ x ] = TOP;
id[ x ] = ++id_cnt;
if( son[ x ] != -1 ) DFS( son[ x ] );
REP( x ) if( id[ e -> to ] == -1 && e -> is )
DFS( TOP = e -> to );
}
void DFS_init() {
clr( id , -1 );
dfs( dep[ 0 ] = 0 );
DFS( TOP = 0 );
}
int set[ maxnode ] , val[ maxnode ];
int L , R , v;
void pushdown( XX ) {
if( set[ x ] != inf && r > l ) {
set[ L( x ) ] = min( set[ L( x ) ] , set[ x ] );
set[ R( x ) ] = min( set[ R( x ) ] , set[ x ] );
set[ x ] = inf;
}
}
void maintain( XX ) {
if( set[ x ] != inf )
val[ x ] = min( val[ x ] , set[ x ] );
}
void update( XX ) {
if( L <= l && r <= R ) {
set[ x ] = min( set[ x ] , v );
} else {
int m = M( l , r );
pushdown( X );
L <= m ? update( LC ) : maintain( LC );
m < R ? update( RC ) : maintain( RC );
}
maintain( X );
}
int query( XX ) {
if( l == r )
return val[ x ];
int m = M( l , r );
pushdown( X );
maintain( LC );
maintain( RC );
return L <= m ? query( LC ) : query( RC );
}
int query_LCA( int x , int y ) {
while( top[ x ] != top[ y ] ) {
if( dep[ top[ x ] ] < dep[ top[ y ] ] )
swap( x , y );
x = fa[ top[ x ] ];
}
return dep[ x ] < dep[ y ] ? x : y;
}
void modify( int x , int y , int d ) {
v = d;
while( top[ x ] != top[ y ] ) {
if( dep[ top[ x ] ] < dep[ top[ y ] ] )
swap( x , y );
L = id[ top[ x ] ] , R = id[ x ];
update( all );
x = fa[ top[ x ] ];
}
if( x != y ) {
if( dep[ x ] < dep[ y ] )
swap( x , y );
L = id[ y ] + 1 , R = id[ x ];
update( all );
}
}
void work() {
rep( x , n ) {
REP( x ) if( ! e -> is ) {
int lca = query_LCA( x , e -> to );
modify( lca , e -> to , d[ x ] + d[ e -> to ] + e -> dist );
}
}
}
inline int read() {
char c = getchar();
int res = 0;
while( ! isdigit( c ) ) c = getchar();
while( isdigit( c ) ) {
res = res * 10 + c - '0';
c = getchar();
}
return res;
}
int main() {
freopen( "test.in" , "r" , stdin );
n = read();
int m = read();
edge_init();
while( m-- ) {
int u = read() , v = read() , d = read();
u-- , v--;
add_edge( u , v , d );
}
dijkstra();
build_tree();
DFS_init();
clr( set , inf );
clr( val , inf );
work();
for( int i = 1 ; i < n ; ++i ) {
L = id[ i ];
int res = query( all );
if( res != inf ) {
printf( "%d\n" , res - d[ i ] );
} else
printf( "-1\n" );
}
return 0;
}
--------------------------------------------------------------------------------
1576: [Usaco2009 Jan]安全路经Travel
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 740 Solved: 254
[Submit][Status][Discuss]
Description
Input
* 第一行: 两个空格分开的数, N和M
* 第2..M+1行: 三个空格分开的数a_i, b_i,和t_i
Output
* 第1..N-1行: 第i行包含一个数:从牛棚_1到牛棚_i+1并且避免从牛棚1到牛棚i+1最短路经上最后一条牛路的最少的时间.如果这样的路经不存在,输出-1.
Sample Input
4 5
1 2 2
1 3 2
3 4 4
3 2 1
2 4 3
输入解释:
跟题中例子相同
1 2 2
1 3 2
3 4 4
3 2 1
2 4 3
输入解释:
跟题中例子相同
Sample Output
3
3
6
输出解释:
跟题中例子相同
3
6
输出解释:
跟题中例子相同
HINT
Source