[bzoj2599] [IOI2011]Race

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

Solution

点分治,基本上是个板子。。

开个桶\(g[i]\)记录路径长度为\(i\)边数最少是多少。

注意无论怎么样\(g[0]\)都会等于\(0\),不要被边权为\(0\)的边影响了。

#include<bits/stdc++.h>
using namespace std;
 
void read(int &x) {
    x=0;int f=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
    for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
}
 
void print(int x) {
    if(x<0) putchar('-'),x=-x;
    if(!x) return ;print(x/10),putchar(x%10+48);
}
void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');}

const int maxn = 1e6+10;
const int maxm = 1e6+10;
const int inf = 1e9;

int vis[maxn],f[maxn],sz[maxn],g[maxm],head[maxn],tot,n,k,rt,size,ans=1e9;
struct edge{int to,nxt,w;}e[maxn<<1];

void add(int u,int v,int w) {e[++tot]=(edge){v,head[u],w},head[u]=tot;}
void ins(int u,int v,int w) {add(u,v,w),add(v,u,w);}

void get_rt(int x,int fa) {
	sz[x]=1,f[x]=0;
	for(int i=head[x];i;i=e[i].nxt)
		if((!vis[e[i].to])&&e[i].to!=fa) 
			get_rt(e[i].to,x),sz[x]+=sz[e[i].to],f[x]=max(f[x],sz[e[i].to]);
	f[x]=max(f[x],size-sz[x]);
	if(f[x]<f[rt]) rt=x;
}

void get_sz(int x,int fa) {
	sz[x]=1;
	for(int i=head[x];i;i=e[i].nxt)
		if((!vis[e[i].to])&&e[i].to!=fa) get_sz(e[i].to,x),sz[x]+=sz[e[i].to];
}

void get_ans(int x,int fa,int dep,int dis) {
	if(dis>k) return ;
	ans=min(ans,dep+g[k-dis]);
	for(int i=head[x];i;i=e[i].nxt)
		if((!vis[e[i].to])&&e[i].to!=fa) get_ans(e[i].to,x,dep+1,dis+e[i].w);
}

void get_dp(int x,int fa,int dep,int dis) {
	if(dis>k) return ;
	g[dis]=min(g[dis],dep);
	for(int i=head[x];i;i=e[i].nxt)
		if((!vis[e[i].to])&&e[i].to!=fa) get_dp(e[i].to,x,dep+1,dis+e[i].w);
}

void clear(int x,int fa,int dis) {
	if(dis>k) return ;
	g[dis]=inf;
	for(int i=head[x];i;i=e[i].nxt)
		if((!vis[e[i].to])&&e[i].to!=fa) clear(e[i].to,x,dis+e[i].w);
}

void solve(int x) {
	vis[x]=1;
	for(int i=head[x];i;i=e[i].nxt)
		if(!vis[e[i].to]) g[0]=0,get_ans(e[i].to,x,1,e[i].w),get_dp(e[i].to,x,1,e[i].w);
	for(int i=head[x];i;i=e[i].nxt)
		if(!vis[e[i].to]) clear(e[i].to,x,e[i].w);
	for(int i=head[x];i;i=e[i].nxt)
		if(!vis[e[i].to]) 
			get_sz(e[i].to,0),size=sz[e[i].to],rt=0,get_rt(e[i].to,0),solve(rt);
}

int main() {
	read(n),read(k);memset(g,63,sizeof g);g[0]=0;
	for(int x,y,z,i=1;i<n;i++) read(x),read(y),read(z),ins(x+1,y+1,z);
	size=n,f[0]=maxn+1,rt=0,get_rt(1,0),solve(rt);write(ans==inf?-1:ans);
	return 0;
}
posted @ 2018-12-27 16:30  Hyscere  阅读(128)  评论(0编辑  收藏  举报