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
HINT
2018.1.3新加数据一组,未重测
Source
很简单的一道点分治,注意一下维护的顺序,先更新答案再更新桶数组
代码:
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #define M 200010
5 using namespace std;
6 int n,m,num,rt,ans,k,S;
7 int maxn[M],head[M],dis[M],d[M],size[M],t[M<<3];
8 bool vis[M];
9 struct point{int to,next,dis;}e[M<<1];
10 void add(int from,int to,int dis) {
11 e[++num].next=head[from];
12 e[num].to=to;
13 e[num].dis=dis;
14 head[from]=num;
15 }
16 void getroot(int x,int fa) {
17 size[x]=1;maxn[x]=0;
18 for(int i=head[x];i;i=e[i].next) {
19 int to=e[i].to;
20 if(to==fa||vis[to]) continue;
21 getroot(to,x),size[x]+=size[to];
22 maxn[x]=max(maxn[x],size[to]);
23 }
24 maxn[x]=max(maxn[x],S-size[x]);
25 if(maxn[x]<maxn[rt]) rt=x;
26 }
27 void cal(int x,int fa) {
28 if(dis[x]>k) return;
29 ans=min(ans,d[x]+t[k-dis[x]]);
30 for(int i=head[x];i;i=e[i].next) {
31 int to=e[i].to;
32 if(vis[to]||to==fa) continue;
33 d[to]=d[x]+1,dis[to]=dis[x]+e[i].dis;
34 cal(to,x);
35 }
36 }
37 void insert(int x,int fa) {
38 if(dis[x]<=k) {
39 t[dis[x]]=min(t[dis[x]],d[x]);
40 for(int i=head[x];i;i=e[i].next)
41 if(!vis[e[i].to]&&e[i].to!=fa)
42 insert(e[i].to,x);
43 }
44 }
45 void del(int x,int fa) {
46 if(dis[x]<=k) {
47 t[dis[x]]=1e9;
48 for(int i=head[x];i;i=e[i].next)
49 if(!vis[e[i].to]&&e[i].to!=fa)
50 del(e[i].to,x);
51 }
52 }
53 void solve(int x) {
54 vis[x]=true;t[0]=0;
55 for(int i=head[x];i;i=e[i].next) {
56 int to=e[i].to;
57 if(vis[to]) continue;
58 d[to]=1,dis[to]=e[i].dis,cal(to,0);
59 insert(to,x);
60 }
61 for(int i=head[x];i;i=e[i].next)
62 if(!vis[e[i].to])
63 del(e[i].to,x);
64 for(int i=head[x];i;i=e[i].next) {
65 int to=e[i].to;
66 if(vis[to]) continue;
67 rt=0,S=size[to],getroot(to,0);
68 solve(rt);
69 }
70 }
71 int main() {
72 scanf("%d%d",&n,&k);ans=n+1;
73 memset(t,1,sizeof(t));
74 for(int i=1;i<n;i++) {
75 int a,b,c;scanf("%d%d%d",&a,&b,&c);
76 a++,b++;
77 add(a,b,c),add(b,a,c);
78 }
79 S=maxn[0]=n;getroot(1,0);
80 solve(rt);
81 if(ans>n) puts("-1");
82 else printf("%d\n",ans);
83 return 0;
84 }