题目描述

给一棵树,每条边有权。求一条简单路径,权值和等于 KK ,且边的数量最小。

输入输出格式

输入格式:

 

第一行:两个整数 n,kn,k 。

第二至 nn 行:每行三个整数,表示一条无向边的两端和权值 (注意点的编号从 00 开始)。

 


输出格式:

 

一个整数,表示最小边数量。

如果不存在这样的路径,输出 -1−1 。

 

输入输出样例

输入样例#1: 

4 3
0 1 1
1 2 2
1 3 4
输出样例#1: 

2

说明

n\le 200000,K\le 1000000n≤200000,K≤1000000 。

题解:谁说点分一定要套容斥的?

这题的暴力思路大约跟dp有点像,每次爆枚到一棵子树中每一个点的距离,显然对于这些距离di,能与他产生解的是之前所有子树中到达距离为k-di的点的最小深度。

然后就是一遍dfs爆枚所有点,再一遍dfs更新所有最小深度,然后就可以a掉了

代码如下:

#include<map>
#include<set>
#include<queue>
#include<cmath>
#include<cstdio>
#include<string>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#define mp make_pair
#define pii pair<int,int>
#define inf 0x3f3f3f3f
using namespace std;
#define int ll
typedef long long ll;
int n,k,deep[],dis[],size[],fa[],vis[];
int tmp[],ans;
vector<pii> g[]; void get_size(int now,int f)
{
size[now]=;
fa[now]=f;
for(int i=; i<g[now].size(); i++)
{
if(vis[g[now][i].first]||g[now][i].first==f) continue;
get_size(g[now][i].first,now);
size[now]+=size[g[now][i].first];
}
} int get_zx(int now,int f)
{
if(size[now]==) return now;
int son,maxson=-;
for(int i=; i<g[now].size(); i++)
{
if(vis[g[now][i].first]||g[now][i].first==f) continue;
if(size[g[now][i].first]>maxson)
{
maxson=size[g[now][i].first];
son=g[now][i].first;
}
}
int zx=get_zx(son,now);
while(size[zx]<*(size[now]-size[zx])) zx=fa[zx];
return zx;
} void calc(int now,int f,int dep,int di)
{
deep[now]=dep;
dis[now]=di;
if(dis[now]<=k) ans=min(ans,tmp[k-dis[now]]+deep[now]);
else return;
for(int i=; i<g[now].size(); i++)
{
if(vis[g[now][i].first]||g[now][i].first==f) continue;
calc(g[now][i].first,now,dep+,di+g[now][i].second);
}
} void dfs(int now,int f,int kd)
{
if(kd) tmp[dis[now]]=min(tmp[dis[now]],deep[now]);
else tmp[dis[now]]=inf;
for(int i=;i<g[now].size();i++)
{
if(vis[g[now][i].first]||g[now][i].first==f) continue;
dfs(g[now][i].first,now,kd);
}
} void solve(int now)
{
vis[now]=;
tmp[]=;
for(int i=;i<g[now].size();i++)
{
if(vis[g[now][i].first]) continue;
calc(g[now][i].first,,,g[now][i].second);
dfs(g[now][i].first,,);
}
for(int i=;i<g[now].size();i++)
{
if(vis[g[now][i].first]) continue;
dfs(g[now][i].first,,);
}
for(int i=;i<g[now].size();i++)
{
if(vis[g[now][i].first]) continue;
get_size(g[now][i].first,);
int zx=get_zx(g[now][i].first,);
solve(zx);
}
} main()
{
scanf("%lld%lld",&n,&k);
for(int i=;i<n;i++)
{
int from,to,cost;
scanf("%lld%lld%lld",&from,&to,&cost);
g[from+].push_back(mp(to+,cost));
g[to+].push_back(mp(from+,cost));
}
ans=inf;
memset(tmp,0x3f,sizeof(tmp));
solve();
ans==0x3f3f3f3f?puts("-1"):printf("%lld\n",ans);
}

洛谷P4149 [IOI2011]Race(点分治)的更多相关文章

  1. 洛谷$P4149\ [IOI2011]\ Race$ 点分治

    正解:点分治 解题报告: 传送门$QwQ$ 昂先不考虑关于那个长度的限制考虑怎么做? 就开个桶,记录所有边的取值,每次加入边的时候查下是否可行就成$QwQ$ 然后现在考虑加入这个长度的限制?就考虑把这 ...

  2. 模板—点分治B(合并子树)(洛谷P4149 [IOI2011]Race)

    洛谷P4149 [IOI2011]Race 点分治作用(目前只知道这个): 求一棵树上满足条件的节点二元组(u,v)个数,比较典型的是求dis(u,v)(dis表示距离)满足条件的(u,v)个数. 算 ...

  3. 洛谷 4149 [IOI2011]Race——点分治

    题目:https://www.luogu.org/problemnew/show/P4149 第一道点分治! 点分治大约是每次找重心,以重心为根做一遍树形dp:然后对于该根的每个孩子,递归下去.递归之 ...

  4. [洛谷P4149][IOI2011]Race

    题目大意:给一棵树,每条边有边权.求一条简单路径,权值和等于$K$,且边的数量最小. 题解:点分治,考虑到这是最小值,不满足可减性,于是点分中的更新答案的地方计算重复的部分要做更改,就用一个数组记录前 ...

  5. 洛谷 P4149 [IOI2011]Race-树分治(点分治,不容斥版)+读入挂-树上求一条路径,权值和等于 K,且边的数量最小

    P4149 [IOI2011]Race 题目描述 给一棵树,每条边有权.求一条简单路径,权值和等于 KK,且边的数量最小. 输入格式 第一行包含两个整数 n, Kn,K. 接下来 n - 1n−1 行 ...

  6. P4149 [IOI2011]Race 点分治

    思路: 点分治 提交:5次 题解: 刚开始用排序+双指针写的,但是调了一晚上,总是有两个点过不了,第二天发现原因是排序时的\(cmp\)函数写错了:如果对于路径长度相同的,我们从小往大按边数排序,当双 ...

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

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

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

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

  9. 洛谷SP22343 NORMA2 - Norma(分治,前缀和)

    洛谷题目传送门 这题推式子恶心..... 考虑分治,每次统计跨过\(mid\)的所有区间的答案和.\(i\)从\(mid-1\)到\(l\)枚举,统计以\(i\)为左端点的所有区间. 我们先维护好\( ...

随机推荐

  1. java.lang.ClassFormatError: Extra bytes at the end of class file

    在精简JRE过程中,将rt.jar中类通过FileInputStream,FileOutputStream进行拷贝操作出错: java.lang.ClassFormatError: Extra byt ...

  2. mac下mysql5.7.18修改root密码

    参考:http://blog.csdn.net/lijilong_/article/details/70991809 第一步:苹果->系统偏好设置->最下面点MySQL,关闭mysql服务 ...

  3. swoole学习

    <?php ini_set('default_socket_timeout', -1); class serverEmail { public $serv = null; public func ...

  4. U盘启动安装WIN7(包含资源的地址)

    这几天在装win7和linux双系统,整理一下 第一种是在正常的windows下,网上下了镜像之后,装虚拟光驱,然后双击安装,按步骤执行即可,这个没什么好讲的. 第二种是windows坏掉,或者木有系 ...

  5. 解决办法 Field userService in com.sxsj.controller.RegistLoginController required a bean of type

    转自:https://blog.csdn.net/awmw74520/article/details/82687288 APPLICATION FAILED TO START Error starti ...

  6. EF CodeFirst简单实例

    运行环境:VS2012,添加的EntityFramework为6.0.2 版本不用太关心,只要知道原理就行了: 基本代码就这几行: namespace ConsoleApplication1 {    ...

  7. uml 时序图

    1.时序图的概念 时序图定义 : 描述了对象之间传递消息的时间顺序, 用来表示用例中的行为顺序, 是强调消息时间顺序的交互图; 时序图描述的事物: 时序图描述系统中类和类之间的交互, 将这些交互建模成 ...

  8. SQL select 执行顺序

    一.sql语句的执行步骤:1)语法分析,分析语句的语法是否符合规范,衡量语句中各表达式的意义.2)语义分析,检查语句中涉及的所有数据库对象是否存在,且用户有相应的权限.3)视图转换,将涉及视图的查询语 ...

  9. VSS/RSS/PSS/USS

    [VSS/RSS/PSS/USS] Android has a tool called procrank (/system/xbin/procrank), which lists out the me ...

  10. 【LA 3989 训练指南】女士的选择 【稳定婚姻问题】

    我们先来学一下稳定婚姻问题 什么是稳定婚姻问题? 有n个女士和n个男士,他们要一一进行配对.每个男士心中对这n个女士都有一个排名,同理,每个女士心里对n个男性也有一个排名.我们要做的是,在他们配对完成 ...