您的位置:首页 > 其它

bzoj2599: [IOI2011]Race

2016-08-06 10:03 281 查看
Description

给一棵树,每条边有权.求一条简单路径,权值和等于K,且边的数量最小.N <= 200000, K <= 1000000

Input

第一行 两个整数 n, k

第二..n行 每行三个整数 表示一条无向边的两端和权值 (注意点的编号从0开始)

Output

一个整数 表示最小边数量 如果不存在这样的路径 输出-1

Sample Input

4 3

0 1 1

1 2 2

1 3 4

Sample Output

2

颓废了一波的我重新开始更blog了..

这道题比较显然的就是用点分治啊.. 找重心然后再找经过它的所有路径咯..

时间复杂度就是O(nlogn)..

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;
const int Maxn = 200010;
const int Maxk = 1000010;
const int inf = 0x7fffffff;
struct node {
int x, y, next, d;
}a[Maxn*2]; int first[Maxn], len;
void ins ( int x, int y, int d ){
len ++;
a[len].x = x; a[len].y = y; a[len].d = d;
a[len].next = first[x]; first[x] = len;
}
int _min ( int x, int y ){ return x < y ? x : y; }
int n, K, cur, s[Maxn], d[Maxn], f[Maxn], core;
int alls, ans;
int v[Maxk], cnt[Maxk];
bool done[Maxn]; int dep[Maxn];
void dfs ( int x, int fa ){
s[x] = 1; f[x] = 0;
for ( int k = first[x]; k; k = a[k].next ){
int y = a[k].y;
if ( y == fa || done[y] == true ) continue;
dfs ( y, x );
s[x] += s[y];
if ( s[y] > f[x] ) f[x] = s[y];
}
if ( alls-s[x] > f[x] ) f[x] = alls-s[x];
if ( f[core] > f[x] ) core = x;
}
void calc ( int x, int fa ){
if ( d[x] > K ) return;
if ( v[K-d[x]] == cur ) ans = _min ( ans, cnt[K-d[x]]+dep[x] );
for ( int k = first[x]; k; k = a[k].next ){
int y = a[k].y;
if ( y == fa || done[y] == true ) continue;
d[y] = d[x]+a[k].d;
dep[y] = dep[x]+1;
calc ( y, x );
}
}
void update ( int x, int fa ){
if ( d[x] > K ) return;
if ( v[d[x]] != cur ){
v[d[x]] = cur;
cnt[d[x]] = dep[x];
}
else cnt[d[x]] = _min ( cnt[d[x]], dep[x] );
for ( int k = first[x]; k; k = a[k].next ){
int y = a[k].y;
if ( y == fa || done[y] == true ) continue;
update ( y, x );
}
}
void solve ( int x ){
done[x] = true;
cur = x;
v[0] = cur;
cnt[0] = 0;
for ( int k = first[x]; k; k = a[k].next ){
int y = a[k].y;
if ( done[y] == true ) continue;
d[y] = a[k].d;
dep[y] = 1;
calc ( y, x );
update ( y, x );
}
for ( int k = first[x]; k; k = a[k].next ){
int y = a[k].y;
if ( done[y] == true ) continue;
core = 0;
alls = f[0] = s[y];
dfs ( y, 0 );
solve (core);
}
}
int main (){
int i, j, k;
scanf ( "%d%d", &n, &K );
for ( i = 1; i < n; i ++ ){
int x, y, dd;
scanf ( "%d%d%d", &x, &y, &dd ); x ++; y ++;
ins ( x, y, dd ); ins ( y, x, dd );
}
ans = inf;
core = 0;
alls = f[0] = n;
dfs ( 1, 0 );
memset ( done, false, sizeof (done) );
solve (core);
if ( ans == inf ) printf ( "-1\n" );
else printf ( "%d\n", ans );
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: