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)..
给一棵树,每条边有权.求一条简单路径,权值和等于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; }
相关文章推荐
- bzoj 2599: [IOI2011]Race (点分治)
- [BZOJ2599][IOI2011]Race-树上启发式合并(dsu on tree)
- BZOJ2599 [IOI2011]Race 点分治
- 【BZOJ 2599】 [IOI2011]Race 树的点分治
- bzoj 2599: [IOI2011]Race 点分治
- [bzoj2599][IOI2011]Race——点分治
- BZOJ2599: [IOI2011]Race
- BZOJ_2599_[IOI2011]Race_点分治
- 【BZOJ】2599: [IOI2011]Race 点分治
- Bzoj2599:[IOI2011]Race:树的点分治
- BZOJ 2599 IOI 2011 Race 点分治
- 【IOI2011】bzoj2599 Race
- 【BZOJ2599】【IOI2011】Race
- 【BZOJ2599】[IOI2011]Race
- BZOJ2599: [IOI2011]Race
- BZOJ2599: [IOI2011]Race
- bzoj2599: [IOI2011]Race 点分治
- bzoj2599 [IOI2011]Race(点分治)
- bzoj 2599 [IOI2011]Race (点分治)
- BZOJ2599: [IOI2011]Race