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 第二 ...
随机推荐
- jenkins配置邮件通知
参考: https://www.cnblogs.com/imyalost/p/8781759.html 谢谢大佬~
- CAD绘制一个直径标注(com接口VB语言)
主要用到函数说明: _DMxDrawX::DrawDimDiametric 绘制一个直径标注.详细说明如下: 参数 说明 DOUBLE dChordPointX 在被标注的曲线上的第一个点X值 DOU ...
- PAT_A1003#Emergency
Source: PAT A1003 Emergency (25 分) Description: As an emergency rescue team leader of a city, you ar ...
- Django - 一对多创建
1.新创建一个app python manage.py startapp app01 2.在django的setting.py中,填加新增的app名称 3.在app01的models.py中,添加代码 ...
- 通过JS唤醒app(安卓+ios)
有需求说要通过页面按钮唤醒app,或者手机上没有这款app跳转到商店,然后刚开始也是查了资料的,结果发现一头雾水,不过最后还是捣鼓出来了,当然也参考了前人分享的经验,下面我就将方法整理一下: 首先明确 ...
- 《啊哈算法》中P81解救小哈
题目描述 首先我们用一个二维数组来存储这个迷宫,刚开始的时候,小哼处于迷宫的入口处(1,1),小哈在(p,q).其实这道题的的本质就在于找从(1,1)到(p,q)的最短路径. 此时摆在小哼面前的路有两 ...
- [luogu3155 CQOI2009] 叶子的染色(树形dp)
传送门 Solution 十分简单的树形dpQwQ,转移关系:父亲染了儿子不用染 只需要确定根就是简单树形dp,而其实根可以随便取一个非叶子节点 可以分情况讨论发现答案并不会改变 Code //By ...
- Django REST framework - 认证
目录 认证 DRF 5种验证方式 如何确定身份验证? 设置身份验证方案 案例: 基于自定义Token认证 第一步: 定义一个用户表和一个保存用户Token的表 第二步: 定义一个登陆视图 第三步定义一 ...
- 远程连接工具putty与mtputty
PuTTY是一个Telnet.SSH.rlogin.纯TCP以及串行接口连接软件 官网 http://www.chiark.greenend.org.uk/~sgtatham/putty/ putty ...
- 【CodeCraft-19 and Codeforces Round #537 (Div. 2) C】Creative Snap
[链接] 我是链接,点我呀:) [题意] 横坐标1..2^n对应着2^n个复仇者的基地,上面有k个复仇者(位置依次给出). 你是灭霸你要用以下方法消灭这k个复仇者: 一开始你获取整个区间[1..2^n ...