bzoj 2599(点分治)
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
0 1 1
1 2 2
1 3 4
Sample Output
/*
开一个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(点分治)的更多相关文章
- bzoj 2599 数分治 点剖分
具体可以见漆子超的论文 /************************************************************** Problem: User: B ...
- BZOJ 2599: [IOI2011]Race( 点分治 )
数据范围是N:20w, K100w. 点分治, 我们只需考虑经过当前树根的方案. K最大只有100w, 直接开个数组CNT[x]表示与当前树根距离为x的最少边数, 然后就可以对根的子树依次dfs并更新 ...
- 【BZOJ 2599】【IOI 2011】Race 点分治
裸的点分治,然而我因为循环赋值$s$时把$i <= k$写成$i <= n$了,WA了好长时间 #include<cstdio> #include<cstring> ...
- bzoj 2599 [IOI2011]Race (点分治)
[题意] 问树中长为k的路径中包含边数最少的路径所包含的边数. [思路] 统计经过根的路径.假设当前枚举到根的第S个子树,若x属于S子树,则有: ans<-dep[x]+min{ dep[y] ...
- BZOJ 2599 Race(树分治)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2599 题意:给一棵树,每条边有权.求一条路径,权值和等于K,且边的数量最小. 题意:每次 ...
- BZOJ 2599 [IOI2011]Race【Tree,点分治】
给出N(1 <= N <= 200000)个结点的树,求长度等于K(1 <= K <= 1000000)的路径的最小边数. 点分治,这道题目和POJ 2114很接近,2114是 ...
- bzoj 2599: [IOI2011]Race (点分治 本地过了就是过了.jpg)
题面:(复制别人的...) Description 给一棵树,每条边有权.求一条路径,权值和等于K,且边的数量最小. Input 第一行 两个整数 n, k第二..n行 每行三个整数 表示一条无向边的 ...
- bzoj 2599: [IOI2011]Race【点分治】
点分治,用一个mn[v]数组记录当前root下长为v的链的最小深度,每次新加一个儿子的时候都在原来儿子更新过的mn数组里更新ans(也就是查一下mn[m-dis[p]]+de[p]) 这里注意更新和初 ...
- 【刷题】BZOJ 2599 [IOI2011]Race
Description 给一棵树,每条边有权.求一条简单路径,权值和等于K,且边的数量最小.N <= 200000, K <= 1000000 Input 第一行 两个整数 n, k 第二 ...
随机推荐
- Python 之糗事百科多线程爬虫案例
import requests from lxml import etree import json import threading import queue # 采集html类 class Get ...
- How To: set udev rule for setting the disk permission on ASM disks when using multipath on Linux 6.x
在RHEL6.4上安装11gR2的RAC时,使用了MULTIPATH来聚合绑定多路径的磁盘,并且修改磁盘的权限,赋予grid:asmadmin用户和组. 此时,在安装时可以发现磁盘,日志如下 INFO ...
- 《啊哈算法》中P81解救小哈
题目描述 首先我们用一个二维数组来存储这个迷宫,刚开始的时候,小哼处于迷宫的入口处(1,1),小哈在(p,q).其实这道题的的本质就在于找从(1,1)到(p,q)的最短路径. 此时摆在小哼面前的路有两 ...
- Robberies (01背包dp变形)
题意:一个强盗要抢劫银行又不想被抓到,所以要进行概率分析求他在不被抓的情况下能抢最多的钱.他给定T(样例个数),N(要抢的银行的个数),P(被抓的概率要小于P)Mj(强盗能抢第j个银行Mj元钱),Pj ...
- Redis防护建议
1.Redis本身防护 (1)不要使用默认端口(6379) (2)增加Redis用户名和密码 (3)在Redis绑定指定IP访问(位置配置文件[redis.config]中的bind节点)2.L ...
- 9.boost权重控制
主要知识点: 学会在should中使用boost进行权重控制 假如现在有一个需求:要把should中某些字段优先显示, 1.不加boost权重控制 GET /forum/article/_se ...
- (ccf)201709-4 通信网络
#include<iostream> #include<memory.h> #include<stack> #include<string> #incl ...
- hdu2007 平方和与立方和【C++】
平方和与立方和 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Sub ...
- VScode使用简介
1.1 VSCode简介 VSCode官网:https://code.visualstudio.com/ 支持语音: 速度较快,对超大文件读写速度飞快(打开10M代码不到1s,Subline原生会卡近 ...
- jQuery WEI----DIV+CSS样式li自动适应高度,自动换行,横向排列
设置相关样式即可,按照需求自己修改样式,Demo代码如下: <li style="display:inline;;line-height:24px;height:auto;word-b ...