2599: [IOI2011]Race

Time Limit: 70 Sec  Memory Limit: 128 MB
Submit:
2590  Solved: 769
[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

HINT

$N<=200000,K<=1000000$

Source

Solution

树的点分治裸题,但是做法有点有趣

开始考虑的是:

正常的点分,然后每次用当前根开始BFS子树,以获得子树中每个节点到根的边权和和路径长度,并利用之前的结果和当前结果更新答案

不过貌似写挂了50s左右炸掉- -

发现其实不需要,只需要开一个100W的数组来记录 当前到根的距离为$i$的路径长度最短值

这样就可以不断对子树进行更新和对答案进行更新了

时间复杂度依旧是$O(nlogn)$

Code

#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
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;
}
#define maxn 200010
#define maxk 1000010
#define inf 0x3f3f3f3f
int n,K;
struct EdgeNode{int next,to,val;}edge[maxn<<];
int head[maxn],cnt=;
void add(int u,int v,int w) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v; edge[cnt].val=w;}
void insert(int u,int v,int w) {add(u,v,w); add(v,u,w);}
int size[maxn],maxx[maxn],num[maxk],siz,root,ans;
bool visit[maxn];
void Getroot(int now,int last)
{
size[now]=; maxx[now]=;
for (int i=head[now]; i; i=edge[i].next)
if (edge[i].to!=last && !visit[edge[i].to])
{
Getroot(edge[i].to,now);
size[now]+=size[edge[i].to];
maxx[now]=max(maxx[now],size[edge[i].to]);
}
maxx[now]=max(maxx[now],siz-size[now]);
if (maxx[now]<maxx[root]) root=now;
}
struct Node{int d,t;}st[maxn];
int s,top;
void DFS(int now,int dis,int tt,int last)
{
if (dis>K) return;
ans=min(ans,tt+num[K-dis]);
st[top++]=Node{dis,tt};
for (int i=head[now]; i; i=edge[i].next)
if (edge[i].to!=last && !visit[edge[i].to])
DFS(edge[i].to,dis+edge[i].val,tt+,now);
}
void Solve(int now)
{
root=; Getroot(now,); now=root;
s=,top=;
for (int i=head[now]; i; i=edge[i].next)
if (!visit[edge[i].to])
{
DFS(edge[i].to,edge[i].val,,now);
for (int j=s; j<=top-; j++)
num[st[j].d]=min(num[st[j].d],st[j].t);
s=top;
}
for (int i=; i<=top-; i++) num[st[i].d]=inf; num[]=;
visit[now]=;
for (int i=head[now]; i; i=edge[i].next)
if (!visit[edge[i].to])
siz=size[edge[i].to],Solve(edge[i].to);
}
int main()
{
n=read(); K=read();
for (int u,v,w,i=; i<=n-; i++) u=read()+,v=read()+,w=read(),insert(u,v,w);
memset(num,inf,sizeof(num)); num[]=;
ans=inf;
siz=maxx[]=n; Solve();
if (ans!=inf) {printf("%d\n",ans); return ;}
puts("-1");
return ;
}

AC第一道IOI   ovo!

【BZOJ-2599】Race 点分治的更多相关文章

  1. BZOJ 2599 Race(树分治)

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

  2. [BZOJ 3456]城市规划(cdq分治+FFT)

    [BZOJ 3456]城市规划(cdq分治+FFT) 题面 求有标号n个点无向连通图数目. 分析 设\(f(i)\)表示\(i\)个点组成的无向连通图数量,\(g(i)\)表示\(i\)个点的图的数量 ...

  3. [BZOJ 2989]数列(CDQ 分治+曼哈顿距离与切比雪夫距离的转化)

    [BZOJ 2989]数列(CDQ 分治) 题面 给定一个长度为n的正整数数列a[i]. 定义2个位置的graze值为两者位置差与数值差的和,即graze(x,y)=|x-y|+|a[x]-a[y]| ...

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

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

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

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. js会员头像上传拖动处理头像类

    js会员头像上传拖动处理头像类 点击下载源码文件

  2. SQL Server之游标的基础知识

    什么是游标: 游标是可以在结果集中上下游动的指针. 游标的作用: --允许定位到结果集中的特定行. --从结果集的当前位置检索一行或多行数据. --支持对结果集中当前位置的行进行修改. 注意:游标虽然 ...

  3. QT QDateTime类、QTimer类

    QDateTime类,头文件#include <QDateTime> 可以使用QDateTime类来获得系统时间.通过QDateTime::currentDateTime()来获取本地系统 ...

  4. web—第四章css&第五章

     web—第四章css&第五章 终于迎接等待已久的CSS,在没学这个之前,我们只会用一点img,查一点小图片,或者是用style改一下颜色,而且比较麻烦.现在多了个css在文件夹在创建一个cs ...

  5. 扩展欧几里得算法(extgcd)

    相信大家对欧几里得算法,即辗转相除法不陌生吧. 代码如下: int gcd(int a, int b){ return !b ? gcd(b, a % b) : a; } 而扩展欧几里得算法,顾名思义 ...

  6. ZeroClipboard / jquery.zclip.min.js跨浏览器复制插件使用中遇到的问题解决

    之前写过一个淘宝优惠券连接PC端转手机端连接的小工具,当时写到将转换好的url复制到剪切板这块时解决了IE和火狐,就是没办法搞定Chrome,知道可以通过flash搞定,但是觉得太麻烦没有仔细研究. ...

  7. 数据库系统原理——ER模型与关系模型

    原文链接: http://blog.csdn.net/haovip123/article/details/21614887 犹记得第一次看<数据库系统原理>时看天书的感觉,云里雾里:现在已 ...

  8. social emotion computing-感情的分类

    第八节  情感的分类 人的情感复杂多样,可以从不同的观察角度进行分类.由于情感的核心内容是价值,因此人的情感主要必须根据它所反映的价值关系的运动与变化的不同特点来进行分类. 1.根据价值的正负变化方向 ...

  9. LXC的介绍

    LXC又名Linux container,是一种虚拟化的解决方案,这种是内核级的虚拟化.(主流的解决方案Xen ,KVM, LXC) 介绍 通过namespace进行资源的隔离,Gust1下的进程与G ...

  10. iOS -- 隐藏返回按钮

    // 隐藏返回按钮 [self.navigationItem setHidesBackButton:YES];