2599: [IOI2011]Race

Time Limit: 70 Sec  Memory Limit: 128 MB
Submit: 3642  Solved: 1081
[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
 
/*
开一个100W的数组t,t[i]表示权值为i的路径最少边数
找到重心分成若干子树后, 得出一棵子树的所有点到根的权值和x,到根a条边,用t[k-x]+a更新答案,全部查询完后
然后再用所有a更新t[x]
这样可以保证不出现点分治中的不合法情况
把一棵树的所有子树搞完后再遍历所有子树恢复T数组,如果用memset应该会比较慢
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm> #define inf 1000000000
#define maxn 1000005
#define maxx 200005 using namespace std; int n,K,cnt,sum,root,ans,x,y,z;
int tot[maxn],head[maxx],son[maxx],f[maxx],dis[maxx],d[maxx];
bool vis[maxx];
struct edge
{
int to,next,w;
}e[maxx<<]; inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
} void add(int u,int v,int w)
{
e[++cnt].to=v;e[cnt].next=head[u];head[u]=cnt;e[cnt].w=w;
} void get_root(int now,int fa)
{
son[now]=;f[now]=;
for(int i=head[now];i;i=e[i].next)
{
int v=e[i].to;
if(v!=fa&&!vis[v])
{
get_root(v,now);
son[now]+=son[v];f[now]=max(f[now],son[v]);
}
}
f[now]=max(f[now],sum-son[now]);
if(f[now]<f[root]) root=now;
} void cal(int now,int fa)
{
if(dis[now]<=K) ans=min(ans,d[now]+tot[K-dis[now]]);
for(int i=head[now];i;i=e[i].next)
{
int v=e[i].to;
if(!vis[v]&&v!=fa)
{
d[v]=d[now]+;
dis[v]=dis[now]+e[i].w;
cal(v,now);
}
}
} void updata(int now,int fa,int flag)
{
if(dis[now]<=K)
{
if(flag) tot[dis[now]]=min(tot[dis[now]],d[now]);
else tot[dis[now]]=inf;
}
for(int i=head[now];i;i=e[i].next)
{
int v=e[i].to;
if(!vis[v]&&v!=fa)
updata(v,now,flag);
}
} void work(int now)
{
vis[now]=;tot[]=;
for(int i=head[now];i;i=e[i].next)
{
int v=e[i].to;
if(!vis[v])
{
d[v]=;dis[v]=e[i].w;
cal(v,);updata(v,,);
}
}
for(int i=head[now];i;i=e[i].next)
{
int v=e[i].to;
if(!vis[v])
updata(v,,);//去掉重心之后要重新统计
}
for(int i=head[now];i;i=e[i].next)
{
int v=e[i].to;
if(!vis[v])
{
root=;sum=son[v];
get_root(v,);
work(root);
}
}
} int main()
{
n=read();K=read();
for(int i=;i<=K;i++)tot[i]=n;
for(int i=;i<n;i++)
{
x=read();y=read();z=read();
x++;y++;
add(x,y,z);add(y,x,z);
}
ans=sum=f[]=n;get_root(,);
work(root);
if(ans!=n)printf("%d\n",ans);
else puts("-1");
return ;
}

bzoj 2599(点分治)的更多相关文章

  1. bzoj 2599 数分治 点剖分

    具体可以见漆子超的论文 /**************************************************************     Problem:     User: B ...

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

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

  3. 【BZOJ 2599】【IOI 2011】Race 点分治

    裸的点分治,然而我因为循环赋值$s$时把$i <= k$写成$i <= n$了,WA了好长时间 #include<cstdio> #include<cstring> ...

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

    [题意] 问树中长为k的路径中包含边数最少的路径所包含的边数. [思路] 统计经过根的路径.假设当前枚举到根的第S个子树,若x属于S子树,则有: ans<-dep[x]+min{ dep[y] ...

  5. BZOJ 2599 Race(树分治)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2599 题意:给一棵树,每条边有权.求一条路径,权值和等于K,且边的数量最小. 题意:每次 ...

  6. BZOJ 2599 [IOI2011]Race【Tree,点分治】

    给出N(1 <= N <= 200000)个结点的树,求长度等于K(1 <= K <= 1000000)的路径的最小边数. 点分治,这道题目和POJ 2114很接近,2114是 ...

  7. bzoj 2599: [IOI2011]Race (点分治 本地过了就是过了.jpg)

    题面:(复制别人的...) Description 给一棵树,每条边有权.求一条路径,权值和等于K,且边的数量最小. Input 第一行 两个整数 n, k第二..n行 每行三个整数 表示一条无向边的 ...

  8. bzoj 2599: [IOI2011]Race【点分治】

    点分治,用一个mn[v]数组记录当前root下长为v的链的最小深度,每次新加一个儿子的时候都在原来儿子更新过的mn数组里更新ans(也就是查一下mn[m-dis[p]]+de[p]) 这里注意更新和初 ...

  9. 【刷题】BZOJ 2599 [IOI2011]Race

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

随机推荐

  1. (转)学习淘淘商城第二十二课(KindEditor富文本编辑器的使用)

    http://blog.csdn.net/u012453843/article/details/70184155 上节课我们一起学习了怎样解决KindEditor富文本编辑器上传图片的浏览器兼容性问题 ...

  2. FusionCharts 更新 chart data 数据

    var AlarmChart = null; function alarmChartReBuild(totalNum, alarmNum) { var alarmPart = (alarmNum * ...

  3. eclipse的任务列表

    如上图所示,备注加  TODO  ,可以在tasks列表中显示,提示你还有哪些工作需要完善 昨天遇到一个问题,加了  TODO  任务列表里却不显示,后来发现是因为任务列表只显示了前100条,而我的项 ...

  4. querySelector

     this.el.nativeElement.querySelector import {Component, ElementRef, OnInit} from '@angular/core'; 

  5. 常见的CPU指令集介绍

    本文摘自网络   一.X86 是微处理器执行的计算机语言指令集,指一个intel通用计算机系列的标准编号缩写,也标识一套通用的计算机指令集合,属于CISC. 1.1.简介 X86指令集是美国Intel ...

  6. BZOJ 2626: JZPFAR KDtree + 堆

    Code: #include<bits/stdc++.h> #define maxn 200000 #define inf 1000000000000000 #define mid ((l ...

  7. [C++] muParser 的简单使用方法

    关于 muParser 库 许多应用程序需要解析数学表达式.该库的主要目的是提供一种快速简便的方法. muParser是一个用C ++编写的可扩展的高性能数学表达式解析器库. 它的工作原理是将数学表达 ...

  8. (C/C++学习)10.C++文件流

    说明:C++中的文件流分为三种:文件输入流.文件输出流.文件输入/输出流,其对应的类分别为 ifstream.ofstream 和 fstream .由这三个类创建类对象,完成对文件的操作.其中文件的 ...

  9. (ccf)201703-3markdown

    #include<iostream> #include<memory.h> #include<stack> #include<string> #incl ...

  10. Tensorflow读取csv文件(转)

    常用的直接读取方法实例:#加载包 import tensorflow as tf import os #设置工作目录 os.chdir("你自己的目录") #查看目录 print( ...