bzoj 2599: [IOI2011]Race

2599: [IOI2011]Race

Time Limit: 70 Sec  Memory Limit: 128 MB
Submit: 4732  Solved: 1385
[Submit][Status][Discuss]

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新加数据一组,未重测

#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 200010
#define INF 1000000000
using namespace std;
int n,m,num,root,sum,ans;
int son[maxn],head[maxn],dis[maxn],d[maxn],f[maxn],vis[maxn],t[maxn*5];
struct node{int to,pre,v;}e[maxn*2];
void Insert(int from,int to,int v){
    e[++num].to=to;
    e[num].v=v;
    e[num].pre=head[from];
    head[from]=num;
}
void getroot(int x,int father){
    son[x]=1;f[x]=0;
    for(int i=head[x];i;i=e[i].pre){
        int to=e[i].to;
        if(to==father||vis[to])continue;
        getroot(to,x);
        son[x]+=son[to];
        f[x]=max(f[x],son[to]);
    }
    f[x]=max(f[x],sum-son[x]);
    if(f[x]<f[root])root=x;
}
void cal(int x,int father){
    if(dis[x]<=m)ans=min(ans,d[x]+t[m-dis[x]]);
    for(int i=head[x];i;i=e[i].pre){
        int to=e[i].to;
        if(to==father||vis[to])continue;
        d[to]=d[x]+1;
        dis[to]=dis[x]+e[i].v;
        cal(to,x);
    }
}
void add(int x,int father,int flag){
    if(dis[x]<=m){
        if(flag)t[dis[x]]=min(d[x],t[dis[x]]);
        else t[dis[x]]=INF;
    }
    for(int i=head[x];i;i=e[i].pre){
        int to=e[i].to;
        if(to==father||vis[to])continue;
        add(to,x,flag);    
    }
}
void solve(int x){
    vis[x]=1;t[0]=0;
    for(int i=head[x];i;i=e[i].pre){
        int to=e[i].to;
        if(vis[to])continue;
        d[to]=1;dis[to]=e[i].v;
        cal(to,0);
        add(to,0,1);
    }
    for(int i=head[x];i;i=e[i].pre){
        int to=e[i].to;
        if(!vis[to])add(to,0,0);
    }
    for(int i=head[x];i;i=e[i].pre){
        int to=e[i].to;
        if(vis[to])continue;
        sum=son[to];root=0;
        getroot(to,0);
        solve(root);
    }
}
int main(){
    freopen("Cola.txt","r",stdin);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)t[i]=n;
    int x,y,z;
    for(int i=1;i<n;i++){
        scanf("%d%d%d",&x,&y,&z);
        x++;y++;
        Insert(x,y,z);Insert(y,x,z);
    }
    sum=ans=f[0]=n;
    getroot(1,0);
    solve(root);
    if(ans==n)puts("-1");
    else printf("%d\n",ans);
    return 0;
}

 

posted @ 2018-04-12 16:52  Echo宝贝儿  阅读(243)  评论(0编辑  收藏  举报