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. Git简单图文教程

    环境: Windows [版本 10.0.15063]64位 Git-2.14.1 64位[下载] TortoiseGit-2.5.0.0 64位[下载],这是一个Git 客户端,外号"乌龟 ...

  2. 听翁恺老师mooc笔记(13)--类型定义和联合

    typedef 虽然我们知道使用struct这个关键字定义一个结构类型,然后可以使用该结构类型定义变量.但是每次要使用的时候都需要带着struct这个关键字,那么如何摆脱这个关键字哪?C语言提供了一个 ...

  3. Linux安装mongodb总结

    由于自己的博客上线部署时需要用到mongodb来存储图片文件,所以先在本地电脑上安装了mongodb做测试,由于之前没接触过mongodb,所以安装过程中遇到了各种小问题,折腾了好久终于安装好并成功启 ...

  4. bzoj千题计划242:bzoj4034: [HAOI2015]树上操作

    http://www.lydsy.com/JudgeOnline/problem.php?id=4034 dfs序,树链剖分 #include<cstdio> #include<io ...

  5. SQL语句取多列的最小值(排除0)

    经常遇到获取数据表中多个列的最小值和最大值,例如: 获取这 4个价格的最小值和最大值: SELECT( SELECT min(minPrice) FROM ( VALUES (IIF(MarketSi ...

  6. 偶遇vue-awesome-swiper的坑

    最近用vue重构一个移动端的项目,碰到了不少坑,今天拿移动端最著名的轮播插件swiper为例来说,由于这个项目没用UI库,纯手写的样式,沿用老的插件,自然而然的选择了vue-awesome-swipe ...

  7. mui对话框事件

    mui.confirm('生成成功,是否跳转到订单页面?','',['跳转','取消'],function(e){ if(e.index==0){ //点击跳转 }else if(e.index==1 ...

  8. JAVA_SE基础——37.main方法的详解

    主函数 大家都会写吧. 大家一直都不知道为何这样设计,这样设计有什么好处呢? 白话解释: main函数的修饰符是public: 公共的 为何不用private 等等的修饰符 而规定只用public呢? ...

  9. CRC 校验

    匠心零度 转载请注明原创出处,谢谢! 说明 上篇RocketMQ(二):RPC通讯介绍了rocketmq的一些rpc细节,其实这些内容不仅仅是rocketmq内容,任何通信模块基本都是类似的,这块内容 ...

  10. big_menu菜单设置

    1.页面 <script> $(function(){ $('.subnav .content-menu .on').after('<a class="add fb&quo ...