洛谷 P4149 [IOI2011]Race-树分治(点分治,不容斥版)+读入挂-树上求一条路径,权值和等于 K,且边的数量最小
P4149 [IOI2011]Race
题目描述
给一棵树,每条边有权。求一条简单路径,权值和等于 KK,且边的数量最小。
输入格式
第一行包含两个整数 n, Kn,K。
接下来 n - 1n−1 行,每行包含三个整数,表示一条无向边的两端和权值。
注意点的编号从 00 开始。
输出格式
输出一个整数,表示最小边数量。
如果不存在这样的路径,输出 -1−1。
输入输出样例
4 3
0 1 1
1 2 2
1 3 4
2
说明/提示
保证 n \leqslant 2 \times 10^5,n⩽2×105, K \leqslant 10^6K⩽106。
这道题目我是在cf161D的基础上进行操作的,在维护距离的时候,顺带维护一下边数就可以。
具体细节代码写了注释,心塞,初始化写挫了,调了两天。。。
学习博客推荐:
还有一个,没看,关于求重心的
代码:
//点分治
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#pragma GCC optimize(2)
//#define FI(n) FastIO::read(n)
const int inf=0x3f3f3f3f;
const int maxn=2e5+;
const int maxm=1e6+; int head[maxn<<],tot;
int root,allnode,n,m,k;
bool vis[maxn];
int deep[maxn],dis[maxn],siz[maxn],maxv[maxn];//deep为维护边数,dis为距离
int minline[maxm],ret[maxn],num[maxn],tmp[maxn];//minline维护对应距离最小的边数,ret保存距离,num保存边数,tmp保存出现过的距离,初始化minline用到
int ans=inf; namespace IO{//读入挂
char buf[<<],*S,*T;
inline char gc(){
if (S==T){
T=(S=buf)+fread(buf,,<<,stdin);
if (S==T)return EOF;
}
return *S++;
}
inline int read(){
int x; bool f; char c;
for(f=;(c=gc())<''||c>'';f=c=='-');
for(x=c^'';(c=gc())>=''&&c<='';x=(x<<)+(x<<)+(c^''));
return f?-x:x;
}
inline long long readll(){
long long x;bool f;char c;
for(f=;(c=gc())<''||c>'';f=c=='-');
for(x=c^'';(c=gc())>=''&&c<='';x=(x<<)+(x<<)+(c^''));
return f?-x:x;
}
}
using IO::read;
using IO::readll; struct node{
int to,next,val;
}edge[maxn<<]; void add(int u,int v,int w)//前向星存图
{
edge[tot].to=v;
edge[tot].next=head[u];
edge[tot].val=w;
head[u]=tot++;
} void init()//初始化
{
memset(head,-,sizeof head);
memset(vis,false,sizeof vis);
for(int i=;i<=k;i++){//初始化保存最小边数
minline[i]=inf;
}
tot=;
} void get_root(int u,int father)//求重心
{
siz[u]=;maxv[u]=;
for(int i=head[u];~i;i=edge[i].next){
int v=edge[i].to;
if(v==father||vis[v]) continue;
get_root(v,u);
siz[u]+=siz[v];
maxv[u]=max(maxv[u],siz[v]);
} maxv[u]=max(maxv[u],allnode-siz[u]);
if(maxv[u]<maxv[root]) root=u;
} void get_dis(int u,int father)//求距离,维护边数
{
if(dis[u]>k) return ;//超过K,剪枝
ans=min(ans,minline[k-dis[u]]+deep[u]);//更新答案
ret[++ret[]]=dis[u];num[ret[]]=deep[u];//保存新得到的数据,距离和边数 for(int i=head[u];~i;i=edge[i].next){
int v=edge[i].to;
if(v==father||vis[v]) continue;
int w=edge[i].val;
dis[v]=dis[u]+w;//更新距离
deep[v]=deep[u]+;//更新边数
get_dis(v,u);
}
} void cal(int u)
{
int cnt=;
for(int i=head[u];~i;i=edge[i].next){
int v=edge[i].to;
int w=edge[i].val;
if(vis[v]) continue;
ret[]=;dis[v]=w;deep[v]=;//初始化
get_dis(v,u); for(int j=;j<=ret[];j++){
tmp[++cnt]=ret[j];//临时保存出现过的距离
minline[ret[j]]=min(minline[ret[j]],num[j]);//更新距离的最小边数
}
}
for(int i=;i<=cnt;i++){
minline[tmp[i]]=inf;//初始化
}
} void solve(int u)
{
minline[]=;
cal(u);
vis[u]=; for(int i=head[u];~i;i=edge[i].next){
int v=edge[i].to;
if(vis[v]) continue;
allnode=siz[v];
root=;maxv[]=inf;
get_root(v,u);
solve(root);
}
} int main()
{
n=read();k=read();
init();
for(int i=;i<n;i++){
int u=read(),v=read(),w=read();
u++,v++;
add(u,v,w);
add(v,u,w);
}
root=;allnode=n;maxv[]=inf;
get_root(,);
solve(root);
if(ans==inf) printf("-1\n");
else printf("%d\n",ans);
return ;
}
洛谷 P4149 [IOI2011]Race-树分治(点分治,不容斥版)+读入挂-树上求一条路径,权值和等于 K,且边的数量最小的更多相关文章
- 模板—点分治B(合并子树)(洛谷P4149 [IOI2011]Race)
洛谷P4149 [IOI2011]Race 点分治作用(目前只知道这个): 求一棵树上满足条件的节点二元组(u,v)个数,比较典型的是求dis(u,v)(dis表示距离)满足条件的(u,v)个数. 算 ...
- [洛谷P4149][IOI2011]Race
题目大意:给一棵树,每条边有边权.求一条简单路径,权值和等于$K$,且边的数量最小. 题解:点分治,考虑到这是最小值,不满足可减性,于是点分中的更新答案的地方计算重复的部分要做更改,就用一个数组记录前 ...
- 洛谷P4149 [IOI2011]Race(点分治)
题目描述 给一棵树,每条边有权.求一条简单路径,权值和等于 KK ,且边的数量最小. 输入输出格式 输入格式: 第一行:两个整数 n,kn,k . 第二至 nn 行:每行三个整数,表示一条无向边的 ...
- 洛谷$P4149\ [IOI2011]\ Race$ 点分治
正解:点分治 解题报告: 传送门$QwQ$ 昂先不考虑关于那个长度的限制考虑怎么做? 就开个桶,记录所有边的取值,每次加入边的时候查下是否可行就成$QwQ$ 然后现在考虑加入这个长度的限制?就考虑把这 ...
- 【BZOJ2599】[IOI2011]Race 树的点分治
[BZOJ2599][IOI2011]Race Description 给一棵树,每条边有权.求一条简单路径,权值和等于K,且边的数量最小.N <= 200000, K <= 100000 ...
- 洛谷 P2634 [国家集训队]聪聪可可-树分治(点分治,容斥版) +读入挂+手动O2优化吸点氧才过。。。-树上路径为3的倍数的路径数量
P2634 [国家集训队]聪聪可可 题目描述 聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃.两个人都想玩儿电脑(可是他们家只有一台电脑)……遇到这种问题,一 ...
- 洛谷 4149 [IOI2011]Race——点分治
题目:https://www.luogu.org/problemnew/show/P4149 第一道点分治! 点分治大约是每次找重心,以重心为根做一遍树形dp:然后对于该根的每个孩子,递归下去.递归之 ...
- 洛谷 P6199 - [EER1]河童重工(点分治+虚树)
洛谷题面传送门 神仙题. 首先看到这样两棵树的题目,我们肯定会往动态树分治的方向考虑.考虑每次找出 \(T_2\) 的重心进行点分治.然后考虑跨过分治中心的点对之间的连边情况.由于连边边权与两棵树都有 ...
- 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)
To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...
随机推荐
- String类的方法应用
String类的几个方法的应用示例: using System;using System.Collections.Generic;using System.Linq;using System.Text ...
- 不用Pageant告别Pageant Windows10下TortoiseGit和Git配置使用同一SSH密钥
关于Git使用SSH免密连接参考:https://blog.csdn.net/qq_32786873/article/details/80570788 关于Windows10下TortoiseGit使 ...
- 2019 途牛旅游网java面试笔试题 (含面试题解析)
本人5年开发经验.18年年底开始跑路找工作,在互联网寒冬下成功拿到阿里巴巴.今日头条.途牛旅游网等公司offer,岗位是Java后端开发,因为发展原因最终选择去了途牛旅游网,入职一年时间了,也成为 ...
- 2019 边锋游戏java面试笔试题 (含面试题解析)
本人5年开发经验.18年年底开始跑路找工作,在互联网寒冬下成功拿到阿里巴巴.今日头条.边锋游戏等公司offer,岗位是Java后端开发,因为发展原因最终选择去了边锋游戏,入职一年时间了,也成为了面 ...
- poj 2102 A计划
可怜的公主在一次次被魔王掳走一次次被骑士们救回来之后,而今,不幸的她再一次面临生命的考验.魔王已经发出消息说将在T时刻吃掉公主,因为他听信谣言说吃公主的肉也能长生不老.年迈的国王正是心急如焚,告招天下 ...
- Kubemetes
将应用docker化,配合ETCD.kubernetes等工具在容器的层面上实现高可用和负载均衡 容器化部署 容器化部署应用具有灵活.高效的使用资源,容器可以包含其所需的全部文件,如同在虚拟机上部署应 ...
- js设置全局变量与读取全局变量
方法1: 设置: var a = 1; 读取: a window.a window['a'] 方法2: 设置: window.b=2; 读取: b window.b window['b'] 方法3: ...
- [转] Cache 和 Buffer的区别
程序员开发过程中经常会遇到“缓存”.“缓冲”等相似概念,之前没有特别关注,现在停下来做一下总结,才能更好地前行. 先来下枯燥的概念: 1.Cache:缓存区,是高速缓存,是位于CPU和主内存之间的容量 ...
- 英语SouthRedAgate南红玛瑙
南红玛瑙(SouthRedAgate)是玛瑙的一个种类,古称”赤玉”,质地细腻油润,是中国独有的品种.由于产量稀少,老南红玛瑙价格急剧上升.南红玛瑙曾被古人用之入药,养心养血. 现在的南红玛瑙已经和和 ...
- springboot+https+http
http访问不安全,使用https相对好些. 参考网址:https://blog.csdn.net/bock1984/article/details/90116965 操作如下: 1. 使用JDK自带 ...