0
点赞
收藏
分享

微信扫一扫

[BZOJ2599]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

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 }

 



举报

相关推荐

0 条评论