BZOJ2599:[IOI2011]Race(点分治)
Description
给一棵树,每条边有权.求一条简单路径,权值和等于K,且边的数量最小.N <= 200000, K <= 1000000
Input
第一行 两个整数 n, k
第二..n行 每行三个整数 表示一条无向边的两端和权值 (注意点的编号从0开始)
Output
一个整数 表示最小边数量 如果不存在这样的路径 输出-1
Sample Input
0 1 1
1 2 2
1 3 4
Sample Output
2
Solution
开一个100W的数组t,t[i]表示到当前处理的树的根距离为i的最小边数
对于点x,我们要统计经过x的路径的话
就分别统计x的每颗子树,在统计一颗子树的时候用t[i]更新答案
并在每统计完一颗子树后更新t数组
↑这样是为了防止统计答案的时候两个点在同一子树里
Code
#include<iostream>
#include<cstring>
#include<cstdio>
#define N (200000+100)
using namespace std;
struct node
{
int to,next,len;
}edge[N*];
int n,k,sum,root,ans,INF;
int head[N],num_edge;
int depth[N],d[N],size[N],maxn[N];
int dis[N],t[N*];
bool vis[N]; void add(int u,int v,int l)
{
edge[++num_edge].to=v;
edge[num_edge].len=l;
edge[num_edge].next=head[u];
head[u]=num_edge;
} void Get_root(int x,int fa)
{
size[x]=; maxn[x]=;
for (int i=head[x];i!=;i=edge[i].next)
if (edge[i].to!=fa && !vis[edge[i].to])
{
Get_root(edge[i].to,x);
size[x]+=size[edge[i].to];
maxn[x]=max(maxn[x],size[edge[i].to]);
}
maxn[x]=max(maxn[x],sum-size[x]);
if (maxn[x]<maxn[root]) root=x;
} void Calc(int x,int fa)
{
if (dis[x]<=k) ans=min(ans,depth[x]+t[k-dis[x]]);
for (int i=head[x];i!=;i=edge[i].next)
if (!vis[edge[i].to] && edge[i].to!=fa)
{
dis[edge[i].to]=dis[x]+edge[i].len;
depth[edge[i].to]=depth[x]+;
Calc(edge[i].to,x);
}
} void Reset(int x,int fa,int flag)
{
if (dis[x]<=k)
{
if (flag) t[dis[x]]=min(t[dis[x]],depth[x]);
else t[dis[x]]=INF;
}
for (int i=head[x];i!=;i=edge[i].next)
if (edge[i].to!=fa && !vis[edge[i].to])
Reset(edge[i].to,x,flag);
} void Solve(int x)
{
vis[x]=true; t[]=;
for (int i=head[x];i!=;i=edge[i].next)
if (!vis[edge[i].to])
{
depth[edge[i].to]=;
dis[edge[i].to]=edge[i].len;
Calc(edge[i].to,);
Reset(edge[i].to,,);
}
for (int i=head[x];i!=;i=edge[i].next)
if (!vis[edge[i].to])
Reset(edge[i].to,,);
for (int i=head[x];i!=;i=edge[i].next)
if (!vis[edge[i].to])
{
sum=size[edge[i].to];
root=;
Get_root(edge[i].to,);
Solve(root);
} } int main()
{
int u,v,l;
memset(t,0x3f,sizeof(t));
memset(&INF,0x3f,sizeof(INF));
scanf("%d%d",&n,&k);
for (int i=;i<=n-;++i)
{
scanf("%d%d%d",&u,&v,&l);
u++; v++;
add(u,v,l); add(v,u,l);
}
ans=sum=maxn[]=n;
Get_root(,);
Solve(root);
printf("%d",ans==n?-:ans);
}
BZOJ2599:[IOI2011]Race(点分治)的更多相关文章
- [bzoj2599][IOI2011]Race——点分治
Brief Description 给定一棵带权树,你需要找到一个点对,他们之间的距离为k,且路径中间的边的个数最少. Algorithm Analyse 我们考虑点分治. 对于子树,我们递归处理,所 ...
- 【BZOJ-2599】Race 点分治
2599: [IOI2011]Race Time Limit: 70 Sec Memory Limit: 128 MBSubmit: 2590 Solved: 769[Submit][Status ...
- BZOJ 2599: [IOI2011]Race( 点分治 )
数据范围是N:20w, K100w. 点分治, 我们只需考虑经过当前树根的方案. K最大只有100w, 直接开个数组CNT[x]表示与当前树根距离为x的最少边数, 然后就可以对根的子树依次dfs并更新 ...
- [IOI2011]Race 点分治
[IOI2011]Race LG传送门 点分治板子题. 直接点分治统计,统计的时候开个桶维护下就好了. 注(tiao)意(le)细(hen)节(jiu). #include<cstdio> ...
- bzoj2599: [IOI2011]Race(点分治)
写了四五道点分治的题目了,算是比较理解点分治是什么东西了吧= = 点分治主要用来解决点对之间的问题的,比如距离为不大于K的点有多少对. 这道题要求距离等于K的点对中连接两点的最小边数. 那么其实道理是 ...
- [luogu4149][bzoj2599][IOI2011]Race【点分治】
题目描述 给一棵树,每条边有权.求一条简单路径,权值和等于 K,且边的数量最小. 题解 比较明显需要用到点分治,我们定义\(d\)数组表示当前节点到根节点\(rt\)之间有多少个节点,也可以表示有多少 ...
- bzoj2599/luogu4149 [IOI2011]Race (点分治)
点分治.WA了一万年. 重点就是统计答案的方法 做法一(洛谷AC bzojWA 自测WA): 做点x时记到x距离为k的边数最小值为dis[k],然后对每一对有值的dis[i]和dis[K-i],给an ...
- 2019.01.09 bzoj2599: [IOI2011]Race(点分治)
传送门 题意:给一棵树,每条边有权.求一条路径,权值和等于K,且边的数量最小. 思路: 考虑点分治如何合并. 我们利用树形dpdpdp求树的直径的方法,边dfsdfsdfs子树边统计答案即可. 代码: ...
- BZOJ2599 [IOI2011]Race 【点分治】
题目 给一棵树,每条边有权.求一条简单路径,权值和等于K,且边的数量最小.N <= 200000, K <= 1000000 输入格式 第一行 两个整数 n, k 第二..n行 每行三个整 ...
随机推荐
- Linux 服务器 MySql的安装和网站的发布
Linux安装MySql,并配置能通过自己的电脑连接服务器的数据库 昨天安装的MySql,今天上午配置MySql能使用本机连接服务器数据库,服务器时DigitalOcean的,提供了很全面很专业的文档 ...
- 总结:Python学习 和 Python与C/C++交互
本篇仅仅是Python的学习和Python和C++数据对接过程中的一些总结. 由于工作的需要,用一周的时间学习 Python. Python是基于C实现的一门解释型语言,由于其易用性,俘获了不少开发者 ...
- Vue 多路由文件的合并
Vue 多路由文件的合并 1.使用的是ES6 数组的合并方法 let routes = new Set([...routes1, ...homerouters]);2.两个路由文件,导出的实际上就是一 ...
- JAVA基础之——版本控制系统之git
1 版本控制系统是什么 当多人协作开发一套产品时,需要能够保证代码都能够共用,那么版本控制系统就应运而生. 2 GIT 当前用的比较多的是svn和git,本文以git为例进行讲解. git诞生于200 ...
- 秒懂String,StringBuilder与StringBuffer
StringBuilder与StringBuffer: StringBuilder:线程不安全 StringBuffer:线程安全 当我们在字符串缓冲区被多个线程使用时,JVM不能保证StringBu ...
- XML文档的解析—dom4j
XML为可扩展标记语言,它主要是用来保存数据,做配置文件,数据传输载体等.其实就是一个后缀名为.xml的文件. XML命名规则 名称可以含字母.数字以及其他的字符 名称不能以数字或者标点符号开始 名称 ...
- MySQL安装再折腾--编码的设置
一.MySQL的安装 从官网(https://dev.mysql.com/downloads/mysql/)中下载Mac OS X 10.12 (x86, 64-bit), DMG Archive(m ...
- shutil的一些基本用法
import shutil import time import tarfile # 将文件内容拷贝到另一个文件中 shutil.copyfileobj(open('a1', 'r'), open(' ...
- 从JSON中读取数据追加到HTML中
本文来自https://www.jianshu.com/p/04127d74d88c,并非本人原创,只是作为自己学习使用的资料,如有浏览者请点击地址自行到原作者页面浏览 有时候我们需要将json数据直 ...
- javascript函数中with的介绍
/*js函数中with函数的用法分析定义 方便用来引用某个对象中已有的属性但是不能用来给对象添加属性 要给对象创建新的属性 必须明确的引用该对象*/代码格式with(object) statement ...