Brief Description

给定一棵带权树,你需要找到一个点对,他们之间的距离为k,且路径中间的边的个数最少。

Algorithm Analyse

我们考虑点分治。

对于子树,我们递归处理,所以我们只考察经过重心的情况。

我们很容易把所有点的dist和deep预处理出来,所以,问题就转化成了求一个点对,使得

\(dist[i]+dist[j] = K\ and\ Belong[i] \neq Belong[j]\)

开始的时候,我想:这题我做过的!不就是在数列里面设两个指针吗?

然后,我就发现这个方法行不通。因为有重复元素,而这些元素全部需要保留。最坏情况下,仍然是\(\Theta(n^2)\)的复杂度来枚举。

回去看题,发现K的范围还是比较小的。我们开设一个桶记录每个值的最优方案,这样就可以了。具体方法参见hzwer

Code

//[bzoj2599][IOI2011]Race
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <set>
#include <vector>
#ifndef ONLINE_JUDGE
const int maxn = 200;
#else
const int maxn = 200050;
#endif
using std::max;
using std::vector;
using std::min;
int n, m, k, rt, ans, sum;
int tot = 0, deep[maxn], dep[maxn], vis[maxn], size[maxn], f[maxn], t[1000005];
struct edge {
int to, v;
};
vector<edge> G[maxn];
void add_edge(int u, int v, int w) {
G[u].push_back((edge){v, w});
G[v].push_back((edge){u, w});
}
void getroot(int x, int fa) {
size[x] = 1;
f[x] = 0;
for (int i = 0; i < G[x].size(); i++) {
edge &e = G[x][i];
if (!vis[e.to] && e.to != fa) {
getroot(e.to, x);
size[x] += size[e.to];
f[x] = max(f[x], size[e.to]);
}
}
f[x] = max(f[x], sum - size[x]);
if (f[x] < f[rt])
rt = x;
}
void getdeep(int x, int fa) {
if (deep[x] <= k)
ans = min(ans, dep[x] + t[k - deep[x]]);
for (int i = 0; i < G[x].size(); i++) {
edge &e = G[x][i];
if (!vis[e.to] && e.to != fa) {
dep[e.to] = dep[x] + 1;
deep[e.to] = deep[x] + e.v;
getdeep(e.to, x);
}
}
}
void update(int x, int fa, bool flag) {
if (deep[x] <= k) {
if (flag)
t[deep[x]] = min(t[deep[x]], dep[x]);
else
t[deep[x]] = 0x3f3f3f;
}
for (int i = 0; i < G[x].size(); i++) {
edge &e = G[x][i];
if (!vis[e.to] && e.to != fa)
update(e.to, x, flag);
}
}
void work(int x) {
vis[x] = 1;
t[0] = 0;
for (int i = 0; i < G[x].size(); i++) {
edge &e = G[x][i];
if (!vis[e.to]) {
dep[e.to] = 1;
deep[e.to] = e.v;
getdeep(e.to, 0);
update(e.to, 0, 1);
}
}
for (int i = 0; i < G[x].size(); i++) {
edge &e = G[x][i];
if (!vis[e.to])
update(e.to, 0, 0);
}
for (int i = 0; i < G[x].size(); i++) {
edge &e = G[x][i];
if (!vis[e.to]) {
rt = 0;
sum = size[e.to];
getroot(e.to, 0);
work(rt);
}
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("input", "r", stdin);
#endif
scanf("%d %d", &n, &k);
for (int i = 1; i < n; i++) {
int x, y, z;
scanf("%d %d %d", &x, &y, &z);
x++, y++;
add_edge(x, y, z);
}
f[0] = sum = ans = n;
memset(t, 0x3f, sizeof(t));
getroot(1, 0);
work(rt);
printf("%d\n", ans == n ? -1 : ans);
}

[bzoj2599][IOI2011]Race——点分治的更多相关文章

  1. BZOJ2599:[IOI2011]Race(点分治)

    Description 给一棵树,每条边有权.求一条简单路径,权值和等于K,且边的数量最小.N <= 200000, K <= 1000000 Input 第一行 两个整数 n, k 第二 ...

  2. 【BZOJ-2599】Race 点分治

    2599: [IOI2011]Race Time Limit: 70 Sec  Memory Limit: 128 MBSubmit: 2590  Solved: 769[Submit][Status ...

  3. BZOJ 2599: [IOI2011]Race( 点分治 )

    数据范围是N:20w, K100w. 点分治, 我们只需考虑经过当前树根的方案. K最大只有100w, 直接开个数组CNT[x]表示与当前树根距离为x的最少边数, 然后就可以对根的子树依次dfs并更新 ...

  4. [IOI2011]Race 点分治

    [IOI2011]Race LG传送门 点分治板子题. 直接点分治统计,统计的时候开个桶维护下就好了. 注(tiao)意(le)细(hen)节(jiu). #include<cstdio> ...

  5. bzoj2599: [IOI2011]Race(点分治)

    写了四五道点分治的题目了,算是比较理解点分治是什么东西了吧= = 点分治主要用来解决点对之间的问题的,比如距离为不大于K的点有多少对. 这道题要求距离等于K的点对中连接两点的最小边数. 那么其实道理是 ...

  6. [luogu4149][bzoj2599][IOI2011]Race【点分治】

    题目描述 给一棵树,每条边有权.求一条简单路径,权值和等于 K,且边的数量最小. 题解 比较明显需要用到点分治,我们定义\(d\)数组表示当前节点到根节点\(rt\)之间有多少个节点,也可以表示有多少 ...

  7. bzoj2599/luogu4149 [IOI2011]Race (点分治)

    点分治.WA了一万年. 重点就是统计答案的方法 做法一(洛谷AC bzojWA 自测WA): 做点x时记到x距离为k的边数最小值为dis[k],然后对每一对有值的dis[i]和dis[K-i],给an ...

  8. 2019.01.09 bzoj2599: [IOI2011]Race(点分治)

    传送门 题意:给一棵树,每条边有权.求一条路径,权值和等于K,且边的数量最小. 思路: 考虑点分治如何合并. 我们利用树形dpdpdp求树的直径的方法,边dfsdfsdfs子树边统计答案即可. 代码: ...

  9. BZOJ2599 [IOI2011]Race 【点分治】

    题目 给一棵树,每条边有权.求一条简单路径,权值和等于K,且边的数量最小.N <= 200000, K <= 1000000 输入格式 第一行 两个整数 n, k 第二..n行 每行三个整 ...

随机推荐

  1. 3招搞定APP注册作弊

    在说如何应对之前,易盾先给各位盾友梳理移动端APP可能遇到哪些作弊风险.1. 渠道商刷量,伪造大量的下载量和装机量,但没有新用户注册:2. 对于电商.P2P.外卖等平台,会面临散户或者团队刷子的注册- ...

  2. howto:在构建基于debian的docker基础镜像时,更换国内包源

    debian经常被用作构建应用镜像的基础镜像,如微软在构建linux下的dotnetcore基础镜像时,提供了基于debian 8(jessie)和debian 9(stretch)的镜像. 由于这些 ...

  3. 一个关于sql更新的小笔记

    一直在sqlserver下写东西,突然用mysql有些语法发生了改变,有点折腾 (MS SQL Server)语句:update A set  a.Name =   b.Name   from   A ...

  4. P3950部落冲突

    题面 \(Solution:\) 法一:LCT裸题 又好想又好码,只不过常数太大. 法二:树链剖分 每次断边将该边权的值++,连边--,然后边权化点权(给儿子),询问就查询从x到y的路径上的边权和,树 ...

  5. react错误总结

    react-native 错误总结 The development server returned response error code: 500 in react-native https://b ...

  6. 【SSH】——spring的控制反转和依赖注入

    spring是一个轻量级的容器框架,主要是为了使企业的开发变得简单.高效.无论是从大小还是开销来讲,他都可以算是轻量级的,也是非侵入性的. 下图是spring的框架示意图,说到spring,就不得不提 ...

  7. WCF扩展记录服务调用时间

    WCF 提供了许多扩展点供开发人员自定义运行时行为. WCF 在 Channel Layer 之上还提供了一个高级运行时,主要是针对应用程序开发人员.在 WCF 文档中,它常被称为服务模型层(Serv ...

  8. Intellij IDEA将工程打包成jar包并执行

    打开File -> Project Structure -> Artifacts 点击“+”,选择“Jar”,选择Empty或From modules with dependencies, ...

  9. 【bzoj2705】[SDOI2012]Longge的问题 欧拉函数

    题目描述 Longge的数学成绩非常好,并且他非常乐于挑战高难度的数学问题.现在问题来了:给定一个整数N,你需要求出∑gcd(i, N)(1<=i <=N). 输入 一个整数,为N. 输出 ...

  10. WebSocket简单介绍(WebSocket 实战)(3)

    这一节里我们用一个案例来演示怎么使用 WebSocket 构建一个实时的 Web 应用.这是一个简单的实时多人聊天系统,包括客户端和服务端的实现.客户端通过浏览器向聊天服务器发起请求,服务器端解析客户 ...