bzoj2599: [IOI2011]Race

来源:互联网 发布:瘦腿 知乎 编辑:程序博客网 时间:2024/06/06 07:50

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;}
0 0
原创粉丝点击