zoukankan      html  css  js  c++  java
  • [IOI2011]Race

    题目描述

    给一棵树,每条边有权。求一条简单路径,权值和等于 K,且边的数量最小。

    输入输出格式

    输入格式:

    第一行:两个整数 n,k。

    第二至 n行:每行三个整数,表示一条无向边的两端和权值 (注意点的编号从 0 开始)。

    输出格式:

    一个整数,表示最小边数量。

    如果不存在这样的路径,输出 -1

    输入输出样例

    输入样例#1: 
    4 3
    0 1 1
    1 2 2
    1 3 4
    输出样例#1: 
    2

    说明

    N<=2*10^5,K<=1*10^6。

    IOI签到题,裸点分

    #include<bits/stdc++.h>
    #define ll long long
    #define maxn 200005
    #define pb push_back
    using namespace std;
    const int inf=1<<29; 
    int tag[maxn*5],n,k;
    int num,d[maxn],mn,dep[maxn];
    bool done[maxn];
    int siz[maxn],ans=inf,hd[maxn];
    int root,sz,to[maxn*2],tot;
    int ne[maxn*2],val[maxn*2];
    
    inline void add(int uu,int vv,int ww){
        to[++tot]=vv,ne[tot]=hd[uu],hd[uu]=tot,val[tot]=ww;
        to[++tot]=uu,ne[tot]=hd[vv],hd[vv]=tot,val[tot]=ww;
    }
    
    void find_root(int x,int fa){
        siz[x]=1;
        int bal=0;
        for(int i=hd[x];i;i=ne[i]){
            if(to[i]==fa||done[to[i]]) continue;
            find_root(to[i],x);
            siz[x]+=siz[to[i]];
            bal=max(bal,siz[to[i]]);
        }
        
        bal=max(bal,sz-siz[x]);
        if(bal<mn) mn=bal,root=x;
    }
    
    int find_siz(int x,int fa){
        int an=1;
        for(int i=hd[x];i;i=ne[i]) if(to[i]!=fa&&!done[to[i]]){
            an+=find_siz(to[i],x);
        }
        return an;
    }
    
    void get_dep(int x,int fa,int dis,int dp){
        if(dis<=k){
            ans=min(ans,dp+tag[k-dis]);
            d[++num]=dis,dep[num]=dp;
        }
        
        for(int i=hd[x];i;i=ne[i]) if(to[i]!=fa&&!done[to[i]]){
            get_dep(to[i],x,dis+val[i],dp+1);
        }
    }
    
    inline void calc(int x,int dis){
        int pre=num;
        get_dep(x,x,dis,1);
        
        for(int i=pre+1;i<=num;i++) tag[d[i]]=min(tag[d[i]],dep[i]);
    }
    
    inline void work(int x,int trsiz){
        sz=trsiz,mn=inf;
        find_root(x,x);
        done[root]=1;
        
        tag[0]=0;
        for(int i=hd[root];i;i=ne[i]) if(!done[to[i]]){
            calc(to[i],val[i]);
        }
        
        for(int i=1;i<=num;i++) tag[d[i]]=inf;
        num=0,tag[0]=inf;
        
        for(int i=hd[root];i;i=ne[i]) if(!done[to[i]]){
            work(to[i],find_siz(to[i],to[i]));
        }
    }
    
    int main(){
        memset(tag,0x3f,sizeof(tag));
        
        int uu,vv,ww;
        scanf("%d%d",&n,&k);
        for(int i=1;i<n;i++){
            scanf("%d%d%d",&uu,&vv,&ww);
            add(uu,vv,ww);
        }
        
        work(1,n);
        
        if(ans==inf) puts("-1");
        else printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    项目笔记一:新建Razor实现多表联合查询
    2018.11.02 理解context 和_context.
    python 笔记1
    Beautiful Soup 笔记 1基本使用
    zabbix 微信报警
    java异常处理机制 (转载)
    jsoup 对网页中图片解析
    java 异常
    将glove预训练词向量转为word2vector形式
    vscode for mac怎样关闭自动更新
  • 原文地址:https://www.cnblogs.com/JYYHH/p/8361601.html
Copyright © 2011-2022 走看看