2599: [IOI2011]Race

Time Limit: 70 Sec  Memory Limit: 128 MB
Submit: 3934  Solved: 1163
[Submit][Status][Discuss]

Description

给一棵树,每条边有权.求一条简单路径,权值和等于K,且边的数量最小.N <= 200000, K <= 1000000

Input

第一行 两个整数 n, k
第二..n行 每行三个整数 表示一条无向边的两端和权值 (注意点的编号从0开始)

Output

一个整数 表示最小边数量 如果不存在这样的路径 输出-1

Sample Input

4 3
0 1 1
1 2 2
1 3 4

Sample Output

2
考虑点分治,每次对子树进行dfs求出子树中每个点到根的距离并记在dis[i]中,步数记在b[i]中。
同时我们开一个桶tot,记录这颗子树之前的子树中所有dis中步数的最小值。
开一个v的桶记录此时tot桶中记录的数是否为以当前u为根更新的答案。

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<cstdlib>
 5 #include<algorithm>
 6 using namespace std;
 7 struct data {
 8     int to,next,val;
 9 }e[400005];
10 int head[200005],cnt;
11 bool vis[200005];
12 void add(int u,int v,int val) {e[cnt].to=v;e[cnt].next=head[u];e[cnt].val=val;head[u]=cnt++;}
13 int son[200005],f[200005],root,sum;
14 int b[200005],dis[200005],tot[1000005];
15 int n,k;
16 int ans=0;
17 int num;
18 int v[1000005];
19 int tt=0;
20 void findroot(int x,int fa) {
21     son[x]=1;f[x]=0;
22     for(int i=head[x];i>=0;i=e[i].next) {
23         int to=e[i].to;if(to==fa||vis[to]) continue;
24         findroot(to,x);
25         son[x]+=son[to];
26         f[x]=max(f[x],son[to]);
27     }
28     f[x]=max(f[x],sum-son[x]);
29     if(f[x]<f[root]) root=x;
30     return;
31 }
32 void dfs(int x,int fa,int d,int dep) {
33     dis[++num]=d;b[num]=dep;
34     for(int i=head[x];i>=0;i=e[i].next) {
35         int to=e[i].to;if(to==fa||vis[to]) continue;
36         if(d+e[i].val>k) continue;
37         dfs(to,x,d+e[i].val,dep+1);
38     }
39 }
40 void work(int x) {
41     vis[x]=1;
42     bool flag=0;
43     for(int i=head[x];i>=0;i=e[i].next) {
44         num=0;
45         int to=e[i].to;if(vis[to]) continue;
46         if(e[i].val>k) continue;
47         dfs(to,x,e[i].val,1);
48         for(int j=1;j<=num;j++) if(dis[j]==k) ans=min(ans,b[j]);
49         if(flag)
50             for(int j=1;j<=num;j++)
51                 if(dis[j]<=k&&v[k-dis[j]]==x) ans=min(ans,b[j]+tot[k-dis[j]]);
52         for(int j=1;j<=num;j++)
53             if(dis[j]<=k) {
54                 if(v[dis[j]]!=x) v[dis[j]]=x,tot[dis[j]]=b[j];
55                 else tot[dis[j]]=min(tot[dis[j]],b[j]);
56             }
57         flag=1;
58     }
59     for(int i=head[x];i>=0;i=e[i].next) {
60         int to=e[i].to;
61         if(vis[to]) continue;
62         root=0;f[0]=n;sum=son[to];
63         findroot(to,x);
64         work(root);
65     }
66 }
67 int main() {
68     //freopen("gg.in","r",stdin);
69     memset(head,-1,sizeof(head));
70     scanf("%d%d",&n,&k);
71     for(int i=1;i<n;i++) {
72         int u,v,t;
73         scanf("%d%d%d",&u,&v,&t);
74         add(u+1,v+1,t);add(v+1,u+1,t);
75     }
76     sum=n;ans=n;f[0]=n;
77     findroot(1,0);
78     work(root);
79     if(ans==n) printf("-1");
80     else printf("%d",ans);
81 }

View Code

转载于:https://www.cnblogs.com/wls001/p/7756381.html

[BZOJ2599][IOI2011]Race 点分治相关推荐

  1. 【BZOJ-2599】Race 点分治

    2599: [IOI2011]Race Time Limit: 70 Sec  Memory Limit: 128 MB Submit: 2590  Solved: 769 [Submit][Stat ...

  2. 【BZOJ】2599: [IOI2011]Race 点分治

    [题意]给一棵树,每条边有权.求一条简单路径,权值和等于K,且边的数量最小.N <= 200000, K <= 1000000.注意点从0开始编号,无解输出-1. [算法]点分治 [题解] ...

  3. BZOJ 2599: [IOI2011]Race 点分治题解

    Time Limit: 70 Sec Memory Limit: 128 MB Submit: 3811 Solved: 1129 Description 给一棵树,每条边有权.求一条简单路径,权值和 ...

  4. bzoj 2599: [IOI2011]Race(树的点分治)

    2599: [IOI2011]Race Time Limit: 70 Sec  Memory Limit: 128 MB Submit: 3862  Solved: 1144 [Submit][Sta ...

  5. P4149 [IOI2011]Race

    P4149 [IOI2011]Race 题意: 给一棵树,每条边有权.求一条简单路径,权值和等于 k,且边的数量最小. 题解: 用t[i]:长度为i的路径包含的最少边数 按照子树顺序,依次用dep[u ...

  6. 【P4149 [IOI2011]Race】点分治

    P4149 给一棵树,每条边有权.求一条简单路径,权值和等于 K,且边的数量最小. 输入格式 第一行包含两个整数 n, K. 接下来 n - 1 行,每行包含三个整数,表示一条无向边的两端和权值. 注 ...

  7. BZOJ 2599: [IOI2011]Race

    点分治模板 #include<cstdio> #include<algorithm> using namespace std; int cnt,n,K,ans,N,root,F ...

  8. [IOI2011]Race

    题目链接:点这里 Solution: 点分治,算出点对之间的距离,记录所属子树和与跟之间的边数. 对于每个点,记录排序过后位置离自己最近的不同子树的点,记做go[x] 每次二分去更新,若遇到同一子树的 ...

  9. [颓废史]蒟蒻的刷题记录

    QAQ蒟蒻一枚,其实我就是来提供水题库的. 以下记录从2016年开始. 1.1 1227: [SDOI2009]虔诚的墓主人 树状数组+离散化 3132: 上帝造题的七分钟 树状数组 二维区间加减+查 ...

最新文章

  1. 吐槽知乎现任搜索引擎
  2. 转:华为副总裁一封信:透露年薪千万的工作感悟,太震撼了!
  3. 【简明笔记】循环条件的优化
  4. 数据挖掘 -- 分类的模型评估度量
  5. angular模态框位置_angular $modal 模态框
  6. php返回json数组元素,php生成返回json对象数组(json支持中文)
  7. 架构设计工作笔记005---微服务架构中的服务编排了解
  8. 最大公约数之辗转相除法
  9. 【POJ3070】斐波那契数列f[n]的后四位,n达1e+9(矩阵快速幂模版题)
  10. 关于vba word的一些用法
  11. QRCode二维码与PDF417码生成与读取JAVA+HTML
  12. 中科大最新Nature Communications!这样的水净化谁不爱?
  13. 大数据行业调研报告(最新版)
  14. abrt-hook-ccpp
  15. SmartFoxServer 2X管理工具
  16. cad绘制正八边形_什么是CAD?为什么要学CAD?该怎么学CAD?
  17. 关于vue-video-plaer 出现 this.el_.vjs_getProperty is not a function at Flash.buff解决方法
  18. java8之localDateTime, ZoneId, Instant使用
  19. Mysql 使用【information_schema.COLUMNS】批量修改表字段注释
  20. 无线通信系统的基本结构

热门文章

  1. python天气预报的功能介绍_python实现智能语音天气预报
  2. java显示长度和第一个字符_从Java字符串中以长度1的字符串返回的第一个字母的最佳方法是什么?...
  3. .net ad域登录 form认证_golang|给Gitbook做个认证代理
  4. java 日期类代码_java 日期时间处理类
  5. html 访问节点,HTML DOM 访问节点
  6. python调用ffmpeg合并_用ffmpeg命令处理mp4剪切与合并
  7. mysql从表截取信息_mysql中循环截取用户信息并插入到目标表对应的字段中
  8. linux内核源码代码量,Linux内核源代码数量已经超过1000万行
  9. Nginx 实现网站 http、https 配置
  10. python获取最近N天工作日列表、节假日列表