BZOJ 2599 [IOI2011]Race【Tree,点分治】
给出N(1 <= N <= 200000)个结点的树,求长度等于K(1 <= K <= 1000000)的路径的最小边数。
点分治,这道题目和POJ 2114很接近,2114是求是否存在长度为K的边,但是那个K比较大。但是这道题目的K比之小了10倍。
1. 用V[i]表示到当前树根root的路径长度为i 时的点(赋值为root结点即可),这样就可以用来判断两条到根的路径长度之和是否等于K:
结点a的root的距离为i,结点b到root的距离为j,处理完a之后会得到V[i] = root,那么在处理结点b的时候,如果V[K-j] = root,就说明某一个a和b的路径长度为K,此时,就可以更新最小边数了。
2. e[i]表示到当前树根root的路径长度为i 时的边的最小条数。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <iostream>
using namespace std;
#define N 200010
#define inf 0x3f3f3f3f
struct node {
int v, l;
node() {}
node(int _v, int _l): v(_v), l(_l) {};
};
vector<node> g[N];
int n, K, cur, root, size, ans;
int s[N], f[N], d[N], e[N]; //s子树的结点数,f求重心,d子结点到根的距离,e子结点到根的边数
int v[N*10], c[N*10];
bool done[N]; void getroot(int now, int fa) {
int u;
s[now] = 1, f[now] = 0;
for (int i=0; i<g[now].size(); i++)
if ((u = g[now][i].v) != fa && !done[u]) {
getroot(u, now);
s[now] += s[u];
f[now] = max(f[now], s[u]);
}
f[now] = max(f[now], size-s[now]);
if (f[now] < f[root]) root = now;
}
void dfs1(int now, int fa) {
if (d[now] > K) return ;
if (v[K-d[now]] == cur) ans = min(ans, c[K-d[now]]+e[now]);
int u;
for (int i=0; i<g[now].size(); i++)
if ((u = g[now][i].v) != fa && !done[u]) {
d[u] = d[now] + g[now][i].l;
e[u] = e[now] + 1;
dfs1(u, now);
}
}
void dfs2(int now, int fa) {
if (d[now] > K) return ;
if (v[d[now]] != cur) {
c[d[now]] = e[now];
v[d[now]] = cur;
} else c[d[now]] = min(c[d[now]], e[now]);
int u;
for (int i=0; i<g[now].size(); i++)
if ((u = g[now][i].v) != fa && !done[u])
dfs2(u, now);
}
void work(int now) {
v[0] = cur = now + 1;
int u;
for (int i=0; i<g[now].size(); i++)
if (!done[u = g[now][i].v]) {
d[u] = g[now][i].l;
e[u] = 1;
dfs1(u, now);
dfs2(u, now);
}
getroot(now, n); //更新s数组
done[now] = true;
for (int i=0; i<g[now].size(); i++)
if (!done[u = g[now][i].v]) {
f[n] = size = s[u];
getroot(u, root=n);
work(root);
}
}
int main() {
scanf("%d%d", &n, &K);
for (int i=0; i<=n; i++) g[i].clear(); for (int i=1, a, b, c; i<n; i++) {
scanf("%d%d%d", &a, &b, &c);
g[a].push_back(node(b, c));
g[b].push_back(node(a, c));
}
memset(done, false, sizeof(done)); ans = f[n] = size = n;
getroot(0, root=n);
work(root); printf("%d\n", ans < n ? ans : -1); return 0;
}
BZOJ 2599 [IOI2011]Race【Tree,点分治】的更多相关文章
- bzoj 2599 [IOI2011]Race (点分治)
[题意] 问树中长为k的路径中包含边数最少的路径所包含的边数. [思路] 统计经过根的路径.假设当前枚举到根的第S个子树,若x属于S子树,则有: ans<-dep[x]+min{ dep[y] ...
- bzoj 2599: [IOI2011]Race【点分治】
点分治,用一个mn[v]数组记录当前root下长为v的链的最小深度,每次新加一个儿子的时候都在原来儿子更新过的mn数组里更新ans(也就是查一下mn[m-dis[p]]+de[p]) 这里注意更新和初 ...
- BZOJ 2599: [IOI2011]Race( 点分治 )
数据范围是N:20w, K100w. 点分治, 我们只需考虑经过当前树根的方案. K最大只有100w, 直接开个数组CNT[x]表示与当前树根距离为x的最少边数, 然后就可以对根的子树依次dfs并更新 ...
- bzoj 2599 [IOI2011]Race 点分
[IOI2011]Race Time Limit: 70 Sec Memory Limit: 128 MBSubmit: 4768 Solved: 1393[Submit][Status][Dis ...
- bzoj 2599: [IOI2011]Race (点分治 本地过了就是过了.jpg)
题面:(复制别人的...) Description 给一棵树,每条边有权.求一条路径,权值和等于K,且边的数量最小. Input 第一行 两个整数 n, k第二..n行 每行三个整数 表示一条无向边的 ...
- 【刷题】BZOJ 2599 [IOI2011]Race
Description 给一棵树,每条边有权.求一条简单路径,权值和等于K,且边的数量最小.N <= 200000, K <= 1000000 Input 第一行 两个整数 n, k 第二 ...
- BZOJ 2599: [IOI2011]Race
点分治,定权值,求另一关键字最小 不满足前缀加减性 可以按序遍历,用一数组$t[] 来维护路径为i的最小边数$ 再对于一个直系儿子对应的子树,先算距离求答案再更新$t数组,这样就不会重复$ #incl ...
- 2599: [IOI2011]Race
2599: [IOI2011]Race 链接 分析 被memset卡... 点分治,对于重心,遍历子树,记录一个数组T[i],表示以重心为起点的长度为i的路径中最少的边数是多少.然后先遍历子树,更新答 ...
- 【BZOJ】2599: [IOI2011]Race 点分治
[题意]给一棵树,每条边有权.求一条简单路径,权值和等于K,且边的数量最小.N <= 200000, K <= 1000000.注意点从0开始编号,无解输出-1. [算法]点分治 [题解] ...
随机推荐
- ThinkPHP 3.1.2 模板中的变量
一.变量输出 (重点) 1.标量输出 2.数组输出 {$name[1]} {$name['k2']} {$name.k1} 3.对象输出 {$name:k} {$name->k} 二.系统变量 ...
- Warning: Unable to send packet: Error with PF_PACKET send() [11]: Message too long (errno = 90)
今天在使用tcpreplay重放流量时,发现有的数据包没有发送成功: Warning: Unable to send packet: Error with PF_PACKET send() [215] ...
- 腾讯webqq最新password加密算法,hash算法
常常在做webqq机器人,可是最头痛的问题就是腾讯常常加一些验证串来防止robot,如今共享出最新的腾讯password加密算法和hash 算法 hash算法 def webqq_hash(i, a) ...
- windows版的node.js简单示例
1.下载node.exe放到任意目录,假设E:\nodejs\ 2.在E:\nodejs\下新建helloworld.js,输入以下内容,保存关闭 var http = require('http') ...
- 五毛的cocos2d-x学习笔记03-控件
VS2013快捷键:注释,Ctrl+K+C:取消注释Ctrl+K+U.都是单行.要实现多行注释与取消注释,就选中多行.run方法调用了AppDelegate的applicationDidFinishL ...
- Laravel 5.1 ACL权限控制 二 之策略类
随着应用逻辑越来越复杂,要处理的权限越来越多,将所有权限定义在AuthServiceProvider显然不是一个明智的做法,因此Laravel引入了策略类,策略类是一些原生的PHP类,和控制器基于资源 ...
- win7和ubuntu双系统,win7时间晚8小时解决办法。
装了Win7和Ubuntu双系统后发现,使用Ubuntu后再登陆win7时系统显示时间不准确,比实际时间晚了8小时. 搜索后发现原来Linux和Windows的系统时间管理是不同的.Linux是以主板 ...
- 单色VGA显示verilogHDL通用代码
今天做VGA,真是拼凑了好久啊.唉,总算完成了. 本来想偷懒移植,最后还是自己写的代码. //2015/12/13 //designer : pengxiaoen //function : vga c ...
- asp.net mvc 客户端(&)中检测到有潜在危险的 Request.Path 值。
出现这个错误后,试过 <pages validateRequest="false"> <httpRuntime requestValidationMode=&qu ...
- jQuery + svg/vml
流程设计器jQuery + svg/vml(Demo7 - 设计器与引擎及表单一起应用例子) 去年就完成了流程设计器及流程引擎的开发,本想着把流程设计器好好整理一下,形成一个一步一步的开发案例,结 ...