点分治[BZOJ]2599: [IOI2011]Race
来源:互联网 发布:ubuntu切换到windows 编辑:程序博客网 时间:2024/05/17 23:31
题目:给一棵树,每条边有权.求一条简单路径,权值和等于K,且边的数量最小.N <= 200000, K <= 1000000
思路:先找到根,然后求出经过根的路径数最小的方案。在处理一个节点时,用已处理的信息加上当前点的信息来更新答案,t[i]表示距离根为i的节点的最小深度,dis[i]表示i节点离根的距离,ans=min(ans,t[k-dis[i]]+d[i])。处理完根的一个子树后再更新一下信息,可以保证答案经过根。对每个子树分治一下就好了。
#include <cstdio>#include <vector>using namespace std;inline char tc(void){ static char fl[1000000],*A=fl,*B=fl; return A==B&&(B=(A=fl)+fread(fl,1,1000000,stdin),A==B)?EOF:*A++;}inline int read(void){ int a=0;static char c; while((c=tc())<'0'||c>'9'); while(c>='0'&&c<='9') a=a*10+c-'0',c=tc(); return a;}struct Edge{ int to,cost; Edge(int t,int c):to(t),cost(c){}};int n,k,t[1000001],mx[200001],size[200001],d[200001],dis[200001],sum,root,ans=1e9;char vis[200001];vector<Edge>edge[200001];void dfs1(int x,int fa){ register int i; size[x]=1,mx[x]=0; for (i=0;i<edge[x].size();++i) if(!vis[edge[x][i].to]&&edge[x][i].to!=fa) dfs1(edge[x][i].to,x),mx[x]=max(mx[x],size[edge[x][i].to]),size[x]+=size[edge[x][i].to]; mx[x]=max(mx[x],sum-size[x]);mx[x]<mx[root]?root=x:0; return ;}void add(int x,int fa,int flag) { register int i; flag?t[dis[x]]=min(t[dis[x]],d[x]):t[dis[x]]=1e9; for (i=0;i<edge[x].size();++i) if(!vis[edge[x][i].to]&&edge[x][i].to!=fa&&dis[edge[x][i].to]<=k) add(edge[x][i].to,x,flag); return ;}void cal(int x,int fa){ register int i; ans=min(ans,t[k-dis[x]]+d[x]); for (i=0;i<edge[x].size();++i) if(!vis[edge[x][i].to]&&edge[x][i].to!=fa) { d[edge[x][i].to]=d[x]+1; dis[edge[x][i].to]=dis[x]+edge[x][i].cost; if(dis[edge[x][i].to]<=k) cal(edge[x][i].to,x); } return ;}void work(int x){ register int i; vis[x]=1,t[0]=0; for (i=0;i<edge[x].size();++i) if(!vis[edge[x][i].to]) dis[edge[x][i].to]=edge[x][i].cost,d[edge[x][i].to]=1, dis[edge[x][i].to]<=k?cal(edge[x][i].to,0),add(edge[x][i].to,0,1),0:0; for (i=0;i<edge[x].size();++i) if(!vis[edge[x][i].to]) dis[edge[x][i].to]<=k?add(edge[x][i].to,0,0),0:0; for (int i=0;i<edge[x].size();++i) if(!vis[edge[x][i].to]) sum=size[edge[x][i].to],root=0,dfs1(edge[x][i].to,0),work(root); return ;}int main(void){ register int i,x,y,z; n=read(),k=read(); for (i=1;i<=k;++i) t[i]=1e9; for (i=1;i<n;++i) x=read()+1,y=read()+1,z=read(),edge[x].push_back(Edge(y,z)),edge[y].push_back(Edge(x,z)); sum=n,mx[0]=1e9,dfs1(1,0),work(root); return ans==1e9?puts("-1"):printf("%d",ans),0;}
阅读全文
0 0
- BZOJ 2599 [IOI2011]Race【Tree,点分治】
- 【点分治】BZOJ 2599:[IOI2011]Race
- bzoj 2599: [IOI2011]Race (点分治)
- Bzoj 2599: [IOI2011]Race(点分治)
- 点分治[BZOJ]2599: [IOI2011]Race
- 【BZOJ】2599 [IOI2011]Race 点分治
- BZOJ 2599: [IOI2011]Race 点分治题解
- bzoj 2599: [IOI2011]Race 点分治
- 2599: [IOI2011]Race 点分治
- BZOJ 2599 IOI2011 Race 树的点分治
- 【BZOJ 2599】 [IOI2011]Race 树的点分治
- bzoj 2599: [IOI2011]Race(树的点分治)
- 【BZOJ】【P2599】【IOI2011】【Race】【题解】【点分治】
- 2599: [IOI2011]Race|树的点分治
- 【bzoj2559】【IOI2011】【Race】【点分治】
- BZOJ_P2599 [IOI2011]Race(点分治)
- 【bzoj2599】[IOI2011]Race 点分治
- 【BZOJ2599】[IOI2011]Race【点分治】
- 【Linux基础系列之】中断系统(2)-下半部
- IDEA 快捷键,main,sysout 模板设置
- react-native-动画
- 远程连接Ubuntu服务器的mysql出现没有权限错误的解决办法
- CXX0017:错误;没有找到index符号
- 点分治[BZOJ]2599: [IOI2011]Race
- Linux ndk编译 报错 bits/c++configure.h is not found
- 强口令策略
- Python安装模块的几种方法
- 请求合并、传输相关
- 各种编译环境中如何为C++添加命令行参数(Command-line parameter)
- kafka命令操作
- SEH X64(2)
- java高级开发工程师学习路线图