0、题意:给一棵树,每条边有权.求一条路径,权值和等于K,且边的数量最小.

1、分析:水题一道,一波树分治就好

我们可以发现这个题的K是比较小的,才100w,那么我们可以树分治一下,在遍历每一棵子树的时候我们知道要统计两个不同子树之间的权值,如果我们全遍历然后再getans,我们就会发现某个子树自己会和自己进行统计了一下,这样不太好,所有我们每遍历一个子树我们就把这个子树中从x所有长度为k的路径记录上v[k]=边数,记住要取min,然后询问我们还是遍历子树,我们查询v[K - k]然后统计答案。。这样我们就能轻松的查询了,最后别忘记把所有v数组清空,记住不要memset,会TLE,我们还是再次的遍历一下。。

然后我们就AC了

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
#define LL long long
#define M 2000010

inline int read(){
    char ch=getchar(); int x=0,f=1;
    while(ch<'0'||ch>'9'){
        if(ch=='-') f=-1;
        ch=getchar();
    }
    while('0'<=ch&&ch<='9'){
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*f;
}

struct Edge{
    int u,v,w,next;
} G[M];
int head[M],tot;
int mx[M],size[M],ok[M],mi,root;
int n,k,V[M],ans;
int vis[M];

inline void add(int u,int v,int w){
    G[++tot]=(Edge){u,v,w,head[u]};
    head[u]=tot;
}

inline void dfssize(int x,int fa){
    size[x]=1;mx[x]=0;
    for(int i=head[x];i!=-1;i=G[i].next) if(G[i].v!=fa&&!ok[G[i].v]){
        dfssize(G[i].v,x);
        size[x]+=size[G[i].v];
        if(size[G[i].v]>mx[x]) mx[x]=size[G[i].v];
    }
}

inline void getroot(int r,int x,int fa){
    if(size[r]-size[x]>mx[x]) mx[x]=size[r]-size[x];
    if(mx[x]<mi) mi=mx[x],root=x;
    for(int i=head[x];i!=-1;i=G[i].next) if(G[i].v!=fa&&!ok[G[i].v]){
        getroot(r,G[i].v,x);
    }
}

inline void dfs_getans(int x,int fa,int edge,int val){
    if(val>k)return;
    if(val==k){
        ans=min(ans,edge);
        return;
    }
    int o=k-val;
    if(V[o]!=0){
        ans=min(ans,edge+V[o]);
    }
    for(int i=head[x];i!=-1;i=G[i].next) if(G[i].v!=fa&&!ok[G[i].v]){
        dfs_getans(G[i].v,x,edge+1,val+G[i].w);
    }
}

inline void dfs_insert(int x,int fa,int edge,int val){
    if(val>=k)return;
    if(!V[val]) V[val]=edge;
    else V[val]=min(V[val],edge);
    for(int i=head[x];i!=-1;i=G[i].next) if(G[i].v!=fa&&!ok[G[i].v]){
        dfs_insert(G[i].v,x,edge+1,val+G[i].w);
    }
}

inline void dfs_delete(int x,int fa,int edge,int val){
    if(val>=k)return;
    V[val]=0;
    for(int i=head[x];i!=-1;i=G[i].next) if(G[i].v!=fa&&!ok[G[i].v]){
        dfs_delete(G[i].v,x,edge+1,val+G[i].w);
    }
}

inline void solve(int x){
    mi=n; dfssize(x,0);
    getroot(x,x,0);
    ok[root]=1;
    for(int i=head[root];i!=-1;i=G[i].next) if(!ok[G[i].v]){
        dfs_getans(G[i].v,root,1,G[i].w);
        dfs_insert(G[i].v,root,1,G[i].w);
    }
    for(int i=head[root];i!=-1;i=G[i].next) if(!ok[G[i].v]){
        dfs_delete(G[i].v,root,1,G[i].w);
    }
    for(int i=head[root];i!=-1;i=G[i].next) if(!ok[G[i].v]){
        solve(G[i].v);
    }
}

int main(){
    n=read(),k=read();
    memset(head,-1,sizeof(head));
    for(int i=1;i<n;i++){
        int  u=read(),v=read(),w=read();
        u++; v++;
        add(u,v,w); add(v,u,w);
    }
    ans=214748364;
    solve(1);
    if(ans==214748364) puts("-1");
    else printf("%d\n",ans);
    return 0;
}

BZOJ2599——[IOI2011]Race的更多相关文章

  1. [bzoj2599][IOI2011]Race——点分治

    Brief Description 给定一棵带权树,你需要找到一个点对,他们之间的距离为k,且路径中间的边的个数最少. Algorithm Analyse 我们考虑点分治. 对于子树,我们递归处理,所 ...

  2. bzoj1758 [Wc2010]重建计划 & bzoj2599 [IOI2011]Race

    两题都是树分治. 1758这题可以二分答案avgvalue,因为avgvalue=Σv(e)/s,因此二分后只需要判断Σv(e)-s*avgvalue是否大于等于0,若大于等于0则调整二分下界,否则调 ...

  3. bzoj2599: [IOI2011]Race(点分治)

    写了四五道点分治的题目了,算是比较理解点分治是什么东西了吧= = 点分治主要用来解决点对之间的问题的,比如距离为不大于K的点有多少对. 这道题要求距离等于K的点对中连接两点的最小边数. 那么其实道理是 ...

  4. BZOJ2599 [IOI2011]Race

    传送门 点分治,黄学长的选根方法会T掉,换了这个人的选根方法就可以了. 当然,你也可以选择黄学长的奇淫优化 //BZOJ 2599 //by Cydiater //2016.9.23 #include ...

  5. [luogu4149][bzoj2599][IOI2011]Race【点分治】

    题目描述 给一棵树,每条边有权.求一条简单路径,权值和等于 K,且边的数量最小. 题解 比较明显需要用到点分治,我们定义\(d\)数组表示当前节点到根节点\(rt\)之间有多少个节点,也可以表示有多少 ...

  6. 2019.01.09 bzoj2599: [IOI2011]Race(点分治)

    传送门 题意:给一棵树,每条边有权.求一条路径,权值和等于K,且边的数量最小. 思路: 考虑点分治如何合并. 我们利用树形dpdpdp求树的直径的方法,边dfsdfsdfs子树边统计答案即可. 代码: ...

  7. bzoj千题计划160:bzoj2599: [IOI2011]Race

    http://www.lydsy.com/JudgeOnline/problem.php?id=2599 点分治 mi[i] 记录边权和为i时的最少边数 先更新答案,再更新mi数组,换根时清空mi # ...

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

    Description 给一棵树,每条边有权.求一条简单路径,权值和等于K,且边的数量最小.N <= 200000, K <= 1000000 Input 第一行 两个整数 n, k 第二 ...

  9. 【点分治】【哈希表】bzoj2599 [IOI2011]Race

    给nlog2n随便过的跪了,不得已弄了个哈希表伪装成nlogn(当然随便卡,好孩子不要学)…… 不过为啥哈希表的大小开小点就RE啊……?必须得超过数据范围一大截才行……谜 #include<cs ...

随机推荐

  1. 如何写出优雅的css代码 ?

    如何写出优雅的css代码 ? 对于同样的项目或者是一个网页,尽管最终每个前端开发工程师都可以实现相同的效果,但是他们所写的代码一定是不同的.有的优雅,看起来清晰易懂,代码具有可拓展性,这样的代码有利于 ...

  2. 如何使用alt键+数字键盘上的数字键打出特殊符号

    如何使用alt键+数字键盘上的数字键打出特殊符号 有时当我需要画示意图说明一个问题,但是苦于没有合适的符号,因此,这篇博文将简单介绍一些特殊的符号方便自己以及大家使用. 实现原理很简单:所有的字符(包 ...

  3. segmentfault.com mongo出识以及对数组的操作

    https://segmentfault.com/a/1190000003951602 首先推荐个工具,no-sql-manager-for-mongodb-professional,虽然收费,但是每 ...

  4. windows7-PowerDesigner 15.1 的安装图解

    下载 PowerDesigner 15.1 的安装文件和破解文件 破解文件下载地址:http://pan.baidu.com/share/link?shareid=177873&uk=3626 ...

  5. crontab执行脚本中文乱码,手动执行没有问题

    crontab执行脚本中文乱码,手动执行没有问题 产生原因:       这是因为Unix/Linux下使用crontab时的运行环境已经不是用户环境了,因此原本用户下的一些环境变量的设置就失效了.例 ...

  6. MySQL学习笔记——约束

    1.约束是在表上强制执行的数据检验规则,约束主要用于保证数据库的完整性. 2.当表中数据有相互依赖性时,可以保护相关的数据不被删除. 3.大部分数据库支持下面五类完整性约束: - NOT NULL非空 ...

  7. HTML+JS+DOM【选项卡自动切换】

    最终效果图(鼠标无操作会自动切换选项卡): <!DOCTYPE html> <html> <head> <meta charset="gb2312& ...

  8. 表达式拼接Expression<Func<IEntityMapper, bool>> predicate

    /// <summary> /// 重写以筛选出当前上下文的实体映射信息 /// </summary> protected override IEnumerable<IE ...

  9. 【转】【Java】利用反射技术,实现对类的私有方法、变量访问

    java关于反射机制的包主要在java.lang.reflect中,structs,hibernate,spring等框架都是基于java的反射机制. 下面是一个关于利用java的反射机制,实现了对私 ...

  10. 在CentOS上搭建apache和PHP服务器环境(转)

    1.您也可以使用一键自动部署环境的工具,请参见网友开发的这个工具 http://www.centos.bz/2013/08/ezhttp-tutorial/ 2. 安装: wget -c http:/ ...