Description

给一棵树,每条边有非负权.求一条简单路径,权值和等于K,且边的数量最小.N <= 200000, 1 <= 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

题解

做了一上午的狗屎题,其实很水(点分裸题)...老是找不出细节错误....

  • 在每一棵点分治的树中只考虑经过根的路径;

    • (1)某一点到根的路径

      • 只需要算出每个点到根的距离即可判断。
    • (2)来自根节点不同儿子所在子树的两个点构成的路径
      • 每个点相当于有三个参数$belong[i]$,$dis[i]$,$s[i]$,分别表示删除根后属于哪个联通快,到根的路径长度以及路径上的边数;
      • 原问题相当于求$min(s[i]+s[j])$,$belong[i]!=belong[j]$,$dis[i]+dis[j]=k$。
  • 依次处理根的每一棵子树;
  • $f[i]$表示已经处理过的子树中到根距离为$i$的点中$s$值最小为多少;
  • 当处理下一棵子树时,每个点所能匹配的点到根的距离都是固定的,直接拿出对应的$f$值更新答案即可,然后利用这棵子树更新$f$数组;
  • 这样保证了更新答案的两点$belong$值不同,$dis$相加等于$k$,同时直接找出当前最优解。
  • 易发现,所有路径都是在这个方法中考虑过的,显然是可行的。
 //It is made by Awson on 2017.9.20
#include <set>
#include <map>
#include <cmath>
#include <ctime>
#include <queue>
#include <stack>
#include <string>
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define Min(a, b) ((a) < (b) ? (a) : (b))
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define LL long long
using namespace std;
const int N = ;
const int K = ;
const int INF = ~0u>>; inline int Read() {
int sum = ;
char ch = getchar();
while (ch < '' || ch > '') ch = getchar();
while (ch >= '' && ch <= '') sum = (sum<<) + (sum<<) + ch - , ch = getchar();
return sum;
}
int n, k, u, v, c;
struct tt {
int to, cost, next;
}edge[N*+];
int path[N+], top;
int ans = INF;
int size[N+], mxsize[N+];
bool vis[N+];
int minsize, root;
int f[K+]; inline void add(int u, int v, int c) {
edge[++top].to = v;
edge[top].cost = c;
edge[top].next = path[u];
path[u] = top;
}
void dfs_size(int u, int fa) {
size[u] = ;
mxsize[u] = ;
for (int i = path[u]; i; i = edge[i].next)
if ((!vis[edge[i].to]) && edge[i].to != fa) {
dfs_size(edge[i].to, u);
size[u] += size[edge[i].to];
mxsize[u] = Max(mxsize[u], size[edge[i].to]);
}
}
void dfs_getroot(int r, int u, int fa) {
mxsize[u] = Max(mxsize[u], size[r]-size[u]);
if (mxsize[u] < minsize) minsize = mxsize[u], root = u;
for (int i = path[u]; i; i = edge[i].next)
if ((!vis[edge[i].to]) && edge[i].to != fa)
dfs_getroot(r, edge[i].to, u);
}
void dfs_getans(int u, int fa, int cnt, int val) {
if (val > k) return;
if (val == k) {
ans = Min(ans, cnt);
return;
}
int tmp = k-val;
if (f[tmp]) ans = Min(f[tmp]+cnt, ans);
for (int i = path[u]; i; i = edge[i].next)
if ((!vis[edge[i].to]) && edge[i].to != fa)
dfs_getans(edge[i].to, u, cnt+, val+edge[i].cost);
}
void dfs_update(int u, int fa, int cnt, int val) {
if (val >= k) return;
if (!f[val]) f[val] = cnt;
else f[val] = Min(f[val], cnt);
for (int i = path[u]; i; i = edge[i].next)
if ((!vis[edge[i].to]) && edge[i].to != fa)
dfs_update(edge[i].to, u, cnt+, val+edge[i].cost);
}
void dfs_delete(int u, int fa, int val) {
if (val >= k) return;
f[val] = ;
for (int i = path[u]; i; i = edge[i].next)
if ((!vis[edge[i].to]) && edge[i].to != fa)
dfs_delete(edge[i].to, u, val+edge[i].cost);
}
void solve(int x) {
minsize = INF;
dfs_size(x, );
dfs_getroot(x, x, );
vis[root] = true;
for (int i = path[root]; i; i = edge[i].next)
if (!vis[edge[i].to]) {
dfs_getans(edge[i].to, root, , edge[i].cost);
dfs_update(edge[i].to, root, , edge[i].cost);
}
for (int i = path[root]; i; i = edge[i].next)
if (!vis[edge[i].to])
dfs_delete(edge[i].to, root, edge[i].cost);
for (int i = path[root]; i; i = edge[i].next)
if (!vis[edge[i].to])
solve(edge[i].to);
}
void work() {
for (int i = ; i < n; i++) {
u = Read(); v = Read(); c = Read();
u++, v++;
add(u, v, c);
add(v, u, c);
}
ans = INF;
solve();
printf("%d\n", ans == INF ? - : ans);
}
int main() {
int size = << ; //==========//
char *p = (char*)malloc(size) + size; //手 动 扩 栈//
__asm__("movl %0, %%esp\n" :: "r"(p)); //==========//
n = Read(); k = Read();
work();return ;
}

[IOI 2011]Race的更多相关文章

  1. 洛谷 P4149 [ IOI 2011 ] Race —— 点分治

    题目:https://www.luogu.org/problemnew/show/P4149 仍然是点分治: 不过因为是取 min ,所以不能用容斥,那么子树之间就必须分开算,记录桶时注意这个: 每次 ...

  2. 【BZOJ 2599】【IOI 2011】Race 点分治

    裸的点分治,然而我因为循环赋值$s$时把$i <= k$写成$i <= n$了,WA了好长时间 #include<cstdio> #include<cstring> ...

  3. 【IOI 2011】Race

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=2599 [算法] 点分治 [代码] #include<bits/stdc++.h ...

  4. [IOI 2011]ricehub

    Description 乡间有一条笔直而长的路称为“米道”.沿着这条米道上 R 块稻田,每块稻田的坐标均为一个 1 到 L 之间(含 1 和 L)的整数.这些稻田按照坐标以不减的顺序给出,即对于 0 ...

  5. 【题解】Arpa's letter-marked tree and Mehrdad's Dokhtar-kosh paths Codeforces 741D DSU on Tree

    Prelude 很好的模板题. 传送到Codeforces:(* ̄3 ̄)╭ Solution 首先要会DSU on Tree,不会的看这里:(❤ ω ❤). 众所周知DSU on Tree是可以用来处 ...

  6. 【BZOJ-2599】Race 点分治

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

  7. hdu 4123 Bob’s Race 树的直径+rmq+尺取

    Bob’s Race Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Probl ...

  8. USACO Section 4.3 Street Race(图的连通性+枚举)

    虽说是IOI'95,但是也是挺水的..for 第一问,n最大为50,所以可以直接枚举起点和终点之外的所有点,然后dfs判断是否连通:for 第二问,易知答案一定是第一问的子集,所以从第一问中的答案中枚 ...

  9. POJ 4003 Bob’s Race && HDU4123 Bob’s Race (dfs+rmq)

    Bob’s Race Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 378   Accepted: 119 Descript ...

随机推荐

  1. 团队作业4——第一次项目冲刺(Alpha版本) Day 1

    小队@JMUZJB-集美震惊部 一.Daily Scrum Meeting照片 二.Burndown Chart 燃尽图 三.项目进展 1.界面 屏幕开发中,原型设计完毕. 2.服务器 服务器由学校提 ...

  2. 201621123057 《Java程序设计》第5周学习总结

    1. 本周学习总结 1.1 写出你认为本周学习中比较重要的知识点关键词 接口,interface,implements,方法签名,has-a,Comparable,Comparator. 1.2 尝试 ...

  3. Error contacting service. It is probably not running.

    平台:centos-6.3-i386 jdk-7u51 storm 0.9.1 python 2.6.6   hadoop 1.2.1 运行zookeeperd后显示启动成功: JMX enabled ...

  4. Struts2之配置文件中Action的详细配置

    在Struts2之配置一文中,我们知道一个struts配置文件可以分为三部分:常量配置    包含其他配置文件的配置    Action配置  . 这其中 常量配置  和 包含其他配置文件的配置  二 ...

  5. Fluent Interface(流式接口)

    我最初接触这个概念是读自<<模式-工程化实现及扩展>>,另外有Martin fowler大师 所写http://martinfowler.com/bliki/FluentInt ...

  6. Comet之SSE(Server - Sent - Envent,服务器发送事件)

    1.SSE API 先要创建一个新的EventSource对象,并传进一个入口点: var source = new EventSource("myenvent.php"); △: ...

  7. lodash源码分析之获取数据类型

    所有的悲伤,总会留下一丝欢乐的线索,所有的遗憾,总会留下一处完美的角落,我在冰峰的深海,寻找希望的缺口,却在惊醒时,瞥见绝美的阳光! --几米 本文为读 lodash 源码的第十八篇,后续文章会更新到 ...

  8. 第二章 初识JSP

    第二章   初识JSP 一.JSP简述 1.是JSP JSP是指在HTML中嵌入Java脚本语言.全称(Java Server Pages) 当用户通过浏览器访问Web应用时,使用JSP容器对请求的J ...

  9. Zepto.js库touch模块代码解析

    Zepto.js也许并不陌生,专门针对移动端开发,Zepto有一些基本的触摸事件可以用来做触摸屏交互(tap事件.swipe事件),Zepto是不支持IE浏览器的. 下面来解析一些Zepto.js触摸 ...

  10. Linux下安装jmeter

    一.用Xftp上传apache-jmeter-2.13.tgz到Linux系统里 二.解压apache-jmeter-2.13.tgz,tar xzfv apache-jmeter-2.13.tgz ...