bzoj2599&COGS2648 [IOI2011]Race
来源:互联网 发布:成捷讯通信概预算软件 编辑:程序博客网 时间:2024/06/06 07:16
bzoj传送门(权限)
COGS传送门
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
题解
神奇的点分治,并没有使用容斥
开两个数组,分别记录是否有到该点距离为i的点以及到该点距离为i至少需要的边数,边递归边合并答案
ps:COGS上需要开栈
CODE:
#include<cstdio>const int N=2e5+10;const int K=1e6+10;const int INF=1e9;struct edge{ int nxt,to,dis;}a[N<<1];int size[N],F[N],head[N],deep[N],d[N],need[N];int Count[K],tmp[K];bool vis[N];int n,k,x,y,z,num,tot,ans=INF,root,Time,cnt;inline int max(const int &a,const int &b){return a>b?a:b;}inline int min(const int &a,const int &b){return a<b?a:b;}inline void add(int x,int y,int z){ a[++num].nxt=head[x],a[num].to=y,a[num].dis=z,head[x]=num; a[++num].nxt=head[y],a[num].to=x,a[num].dis=z,head[y]=num;}void getroot(int now,int fa){ size[now]=1,F[now]=0; for(int i=head[now];i;i=a[i].nxt) if(a[i].to!=fa&&!vis[a[i].to]) { getroot(a[i].to,now); size[now]+=size[a[i].to]; F[now]=max(F[now],size[a[i].to]); } F[now]=max(F[now],tot-size[now]); if(F[now]<F[root]) root=now;}void getans(int now,int fa,int depth){ deep[++cnt]=d[now]; need[cnt]=depth; for(int i=head[now];i;i=a[i].nxt) if(!vis[a[i].to]&&a[i].to!=fa) { d[a[i].to]=d[now]+a[i].dis; if(d[a[i].to]<=k) getans(a[i].to,now,depth+1); }}inline void calc(int now){ Count[0]=0;tmp[0]=++Time; d[now]=0; for(int i=head[now];i;i=a[i].nxt) if(!vis[a[i].to]) { d[a[i].to]=d[now]+a[i].dis; if(d[a[i].to]>k) continue; cnt=0; getans(a[i].to,0,1); for(int j=1;j<=cnt;j++) { if(tmp[k-deep[j]]!=Time) { Count[k-deep[j]]=INF; tmp[k-deep[j]]=Time; } ans=min(ans,need[j]+Count[k-deep[j]]); } for(int j=1;j<=cnt;j++) { if(tmp[deep[j]]!=Time) { Count[deep[j]]=INF; tmp[deep[j]]=Time; } Count[deep[j]]=min(Count[deep[j]],need[j]); } }}void solve(int now){ vis[now]=1; calc(now); for(int i=head[now];i;i=a[i].nxt) if(!vis[a[i].to]) { root=0;tot=size[a[i].to]; getroot(a[i].to,0); solve(root); }}int main(){ scanf("%d%d",&n,&k); for(int i=1;i<n;i++) scanf("%d%d%d",&x,&y,&z),add(x+1,y+1,z); F[0]=INF;tot=n; getroot(1,0); solve(root); if(ans>n) printf("-1"); else printf("%d",ans); return 0;}
阅读全文
0 0
- bzoj2599&COGS2648 [IOI2011]Race
- 【bzoj2599】: [IOI2011]Race
- BZOJ2599: [IOI2011]Race
- bzoj2599【IOI2011】Race
- bzoj2599: [IOI2011]Race
- bzoj2599: [IOI2011]Race
- BZOJ2599: [IOI2011]Race
- 【IOI2011】bzoj2599 Race
- bzoj2599: [IOI2011]Race
- 【bzoj2599】[IOI2011]Race
- bzoj2599 [IOI2011]Race
- 【BZOJ2599】[IOI2011]Race
- 【bzoj2599】[IOI2011]Race 点分治
- 【BZOJ2599】[IOI2011]Race【点分治】
- BZOJ2599——[IOI2011]Race
- [BZOJ2599][IOI2011]Race 树分治
- BZOJ2599: [IOI2011]Race 点分治
- bzoj2599: [IOI2011]Race 点分治
- 基于C++全局变量的声明与定义的详解
- 重温《并发编程实战》---线程安全性
- @property的使用
- 日常训练 Idiot 的方程
- CSS简介
- bzoj2599&COGS2648 [IOI2011]Race
- Android开发之安卓属性动画大总结
- 程序动画
- 最近学习总结
- 自动打包并发布脚步方法
- IOS 32
- C 标准库 复习
- IOS 33
- 阿里云服务器如何打开端口映射?