点此看题面

大致题意: 给你一棵树,问长度为\(K\)的路径至少由几条边构成。

点分治

这题应该比较显然是点分治

主要思路

与常见的点分治套路一样,由于\(K≤1000000\),因此我们可以考虑开个桶\(f\)数组来记录每种长度的路径至少由几条边构成

但是要注意,每换一个根要将桶清空

呃,暴力清空肯定\(T\)飞。

于是就需要再开一个\(g\)数组,记录每个答案是在以哪一个节点为根时求出来的,这样就可以避免清空数组了。这也是一个比较常用的套路。

其余的过程与点分板子差不多,就不多说了。

代码

#include<bits/stdc++.h>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define uint unsigned int
#define LL long long
#define ull unsigned long long
#define swap(x,y) (x^=y,y^=x,x^=y)
#define abs(x) ((x)<0?-(x):(x))
#define INF 1e9
#define Inc(x,y) ((x+=(y))>=MOD&&(x-=MOD))
#define ten(x) (((x)<<3)+((x)<<1))
#define N 200000
#define K 1000000
#define add(x,y,z) (e[++ee].nxt=lnk[x],e[lnk[x]=ee].to=y,e[ee].val=z)
using namespace std;
int n,k,ee=0,lnk[N+5];
struct edge
{
int to,nxt,val;
}e[2*N+5];
class FIO
{
private:
#define Fsize 100000
#define tc() (FinNow==FinEnd&&(FinEnd=(FinNow=Fin)+fread(Fin,1,Fsize,stdin),FinNow==FinEnd)?EOF:*FinNow++)
#define pc(ch) (FoutSize<Fsize?Fout[FoutSize++]=ch:(fwrite(Fout,1,FoutSize,stdout),Fout[(FoutSize=0)++]=ch))
int f,FoutSize,OutputTop;char ch,Fin[Fsize],*FinNow,*FinEnd,Fout[Fsize],OutputStack[Fsize];
public:
FIO() {FinNow=FinEnd=Fin;}
inline void read(int &x) {x=0,f=1;while(!isdigit(ch=tc())) f=ch^'-'?1:-1;while(x=ten(x)+(ch&15),isdigit(ch=tc()));x*=f;}
inline void read_char(char &x) {while(isspace(x=tc()));}
inline void read_string(string &x) {x="";while(isspace(ch=tc()));while(x+=ch,!isspace(ch=tc())) if(!~ch) return;}
inline void write(int x) {if(!x) return (void)pc('0');if(x<0) pc('-'),x=-x;while(x) OutputStack[++OutputTop]=x%10+48,x/=10;while(OutputTop) pc(OutputStack[OutputTop]),--OutputTop;}
inline void write_char(char x) {pc(x);}
inline void write_string(string x) {register int i,len=x.length();for(i=0;i<len;++i) pc(x[i]);}
inline void end() {fwrite(Fout,1,FoutSize,stdout);}
}F;
class Class_DotSolver//点分治
{
private:
int ans,rt,top,f[K+5],g[K+5],used[N+5],Size[N+5],Max[N+5],dis[N+5],len[N+5],Stack[N+5];
inline void GetRt(int x,int lst,int sum)//找重心做根
{
register int i;
for(i=lnk[x],Size[x]=1,Max[x]=0;i;i=e[i].nxt)
if(e[i].to^lst&&!used[e[i].to]) GetRt(e[i].to,x,sum),Size[x]+=Size[e[i].to],Max[x]=max(Max[x],Size[e[i].to]);
if((Max[x]=max(Max[x],sum-Size[x]))<Max[rt]) rt=x;
}
inline void dfs(int x,int lst)//遍历子树,将各种路径保存下来
{
register int i;
for(i=lnk[Stack[++top]=x];i;i=e[i].nxt)
if(e[i].to^lst&&!used[e[i].to]) dis[e[i].to]=dis[x]+e[i].val,len[e[i].to]=len[x]+1,dfs(e[i].to,x);
}
inline void Solve(int x)//在以x为根的子树中求解
{
register int i,j;
for(i=lnk[x],used[x]=1,g[0]=x;i;i=e[i].nxt)
{
if(used[e[i].to]) continue;
dis[e[i].to]=e[i].val,len[e[i].to]=1,dfs(e[i].to,x);//遍历该子树
for(j=top;j;--j) if(dis[Stack[j]]<=k&&!(g[k-dis[Stack[j]]]^x)) ans=min(ans,len[Stack[j]]+f[k-dis[Stack[j]]]);//更新答案
while(top)
{
if(dis[Stack[top]]<=k) g[dis[Stack[top]]]^x?(g[dis[Stack[top]]]=x,f[dis[Stack[top]]]=len[Stack[top]]):(f[dis[Stack[top]]]=min(f[dis[Stack[top]]],len[Stack[top]]));//更新桶
--top;
}
}
for(i=lnk[x];i;i=e[i].nxt) if(!used[e[i].to]) GetRt(e[i].to,rt=0,Size[e[i].to]),Solve(rt);//继续对子树进行处理
}
public:
inline int GetAns() {return (void)(ans=Max[0]=INF,GetRt(1,rt=0,n),Solve(rt)),ans==INF?-1:ans;}//求答案
}DotSolver;
int main()
{
register int i,x,y,z;
for(F.read(n),F.read(k),i=1;i<n;++i) F.read(x),F.read(y),F.read(z),++x,++y,add(x,y,z),add(y,x,z);//注意细节,是从0开始编号的,所以将x和y各加1
return F.write(DotSolver.GetAns()),F.end(),0;
}

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

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

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

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

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

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

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

  4. 洛谷P4149 [IOI2011]Race(点分治)

    题目描述 给一棵树,每条边有权.求一条简单路径,权值和等于 KK ,且边的数量最小. 输入输出格式 输入格式:   第一行:两个整数 n,kn,k . 第二至 nn 行:每行三个整数,表示一条无向边的 ...

  5. [洛谷P4149][IOI2011]Race

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

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

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

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

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

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

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

  9. bzoj2599/luogu4149 [IOI2011]Race (点分治)

    点分治.WA了一万年. 重点就是统计答案的方法 做法一(洛谷AC bzojWA 自测WA): 做点x时记到x距离为k的边数最小值为dis[k],然后对每一对有值的dis[i]和dis[K-i],给an ...

  10. [IOI2011]Race 点分治

    [IOI2011]Race LG传送门 点分治板子题. 直接点分治统计,统计的时候开个桶维护下就好了. 注(tiao)意(le)细(hen)节(jiu). #include<cstdio> ...

随机推荐

  1. hdu3830(lca + 二分)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3830 题意: 有三个点 a, b, c, 对于其中任意一点 x 可以跨过一个点移动到另一个位置, 当 ...

  2. Problem C: [noip2016十连测第五场]travel (构造+贪心)

    题面 https://www.lydsy.com/JudgeOnline/upload/201610/statements(1).pdf 题解 好神仙的贪心-- 首先无解的情况很容易判断,就是\(l= ...

  3. Hadoop 2.0完全分布式集群搭建方法(CentOS7+Hadoop 2.7.7)

    本文详细介绍搭建4个节点的完全分布式Hadoop集群的方法,Linux系统版本是CentOS 7,Hadoop版本是2.7.7,JDK版本是1.8. 一.准备环境 1. 在VMware worksta ...

  4. 怎么在Vue中使用Base64格式的背景

    问题发生于一次mock数据,生成了base64格式的东西,因为编码包在一个变量中,不知道怎么直接在 :style 中引入. 解答1:格式background-image: url(此处是我们mock生 ...

  5. Swing实现canvas-nest.js 源码

    #### 说明 canvas-nest.js 源码 http://www.bubuko.com/infodetail-2237716.html 地址:https://gitee.com/dgwcode ...

  6. 2017 ACM/ICPC Asia Regional Shenyang Online card card card

    题意:看后面也应该知道是什么意思了 解法: 我们设置l,r,符合条件就是l=起始点,r=当前点,不符合l=i+1 学习了一下FASTIO #include <iostream> #incl ...

  7. 洛谷P5279 [ZJOI2019]麻将

    https://www.luogu.org/problemnew/show/P5279 以下为个人笔记,建议别看: 首先考虑如何判一个牌型是否含有胡的子集.先将牌型表示为一个数组num,其中num[i ...

  8. Java中如何实现代理机制(JDK动态代理和cglib动态代理)

    http://blog.csdn.net/skiof007/article/details/52806714 JDK动态代理:代理类和目标类实现了共同的接口,用到InvocationHandler接口 ...

  9. 精心收集的SSH框架的面试题汇总

    Hibernate工作原理及为什么要用? 原理: 1. 读取并解析配置文件 2. 读取并解析映射信息,创建SessionFactory 3. 打开Sesssion 4. 创建事务Transation ...

  10. <Openssl下hash函数>

    hash函数:是不可逆的函数,它的输入可以是任意长度的字节流.它的输出是固定大小的,hash函数的作用就是给你的文件产生一个摘要,它是独一无二的. 例如:y=f(x) x代表输入  y代表输出   输 ...