BZOJ2599: [IOI2011]Race

题目链接

%%%http://hzwer.com/4286.html

【代码】

#include <iostream>  
#include <cstdio> 
#include <string> 
#include <cstring>
#include <vector>
#include <queue>
#include <map>
#include <stack>
#include <algorithm>
#include <set>
#include <cmath>
#define N 200010
#define INF 1000000000
#define eps 1e-6
using namespace std;
typedef long long LL;
int n,k;
struct edge{
    int b,nt,w;
}e[N*2];
int p[N],nn;
void anode(int x,int y,int z){
    nn++;e[nn].b=y;e[nn].nt=p[x];p[x]=nn;e[nn].w=z;
    nn++;e[nn].b=x;e[nn].nt=p[y];p[y]=nn;e[nn].w=z;
}

int cnt[N*5];
int sz[N],f[N],sum,root,flag[N];
void getroot(int x,int fa){
    sz[x]=1;f[x]=0;
    for(int i=p[x];i;i=e[i].nt){
        int t=e[i].b;
        if(t==fa||flag[t])continue;
        getroot(t,x);sz[x]+=sz[t];f[x]=max(f[x],sz[t]);
    }f[x]=max(f[x],sum-sz[x]);
    if(f[x]<f[root])root=x;
}
int deep[N],dis[N];
void getd(int x,int dp,int d,int fa){
    deep[++deep[0]]=dp;dis[++dis[0]]=d;
    for(int i=p[x];i;i=e[i].nt){
        int t=e[i].b;
        if(t==fa||flag[t])continue;
        getd(t,dp+1,d+e[i].w,x);
    }
}
int ans=1000000000;

void Erase(int x,int d,int fa){
    if(d>k)return;
    cnt[d]=1000000000;
    for(int i=p[x];i;i=e[i].nt){
        int t=e[i].b;
        if(flag[t]||t==fa)continue;
        Erase(t,d+e[i].w,x);
    }
}

void solve(int x){
    flag[x]=1;
    for(int i=p[x];i;i=e[i].nt){
        int t=e[i].b;deep[0]=dis[0]=0;cnt[0]=0;
        if(flag[t])continue;
        getd(t,1,e[i].w,x);
        for(int j=1;j<=deep[0];j++)
            if(dis[j]<=k)ans=min(ans,cnt[k-dis[j]]+deep[j]);
        for(int j=1;j<=deep[0];j++)
            if(dis[j]<=k)cnt[dis[j]]=min(cnt[dis[j]],deep[j]);
    }
    for(int i=p[x];i;i=e[i].nt){
        int t=e[i].b;
        if(flag[t])continue;
        Erase(t,e[i].w,x);
    }
    for(int i=p[x];i;i=e[i].nt){
        int t=e[i].b;
        if(flag[t])continue;
        root=0;sum=sz[t];
        getroot(t,x);
        solve(root);
    } 
}

int main()  
{  
    scanf("%d%d",&n,&k);
    sum=n;f[0]=1e9;
    for(int i=1;i<=k;i++)cnt[i]=1e9;
    for(int i=1;i<n;i++){
        int aa,bb,cc;scanf("%d%d%d",&aa,&bb,&cc);
        aa++;bb++;anode(aa,bb,cc);
    } 
    getroot(1,0);
    solve(root);
    if(ans==1e9)ans=-1;
    printf("%d\n",ans);
    return 0;  
}  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值