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

    Description

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

    Solution

    点分治,统计答案时只统计经过该节点的所有链(包括以该节点为端点)

    每次用桶维护之前的子树中每个路径权值和所对应的最少边数

    时间复杂度$O(n log n)$

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    int n,K,head[200005],tot,allsiz,maxx[200005],root,siz[200005],buc[1000005],cnt,d1[200005],d2[200005],ans=1<<30;
    bool vst[200005];
    struct Edge{
        int to,nxt,w;
    }edge[400005];
    inline int read(){
        int w=0,f=1;
        char ch=0;
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
        while(ch>='0'&&ch<='9')w=(w<<1)+(w<<3)+ch-'0',ch=getchar();
        return w*f;
    }
    void getroot(int k,int fa){
        siz[k]=1,maxx[k]=0;
        for(int i=head[k];i;i=edge[i].nxt){
            int v=edge[i].to;
            if(v!=fa&&!vst[v])getroot(v,k),siz[k]+=siz[v],maxx[k]=max(maxx[k],siz[v]);
        }
        maxx[k]=max(maxx[k],allsiz-siz[k]);
        if(maxx[k]<maxx[root])root=k;
    }
    void getdis(int k,int fa,int w1,int w2){
        if(w1>K)return;
        d1[++cnt]=w1,d2[cnt]=w2;
        for(int i=head[k];i;i=edge[i].nxt){
            int v=edge[i].to;
            if(!vst[v]&&v!=fa)getdis(v,k,edge[i].w+w1,w2+1);
        }
    }
    void calc(int k){
        buc[0]=cnt=0;
        for(int i=head[k];i;i=edge[i].nxt){
            int v=edge[i].to;
            if(!vst[v]){
                int tag=cnt;
                getdis(v,k,edge[i].w,1);
                for(int j=tag+1;j<=cnt;j++)ans=min(ans,buc[K-d1[j]]+d2[j]);
                for(int j=tag+1;j<=cnt;j++)buc[d1[j]]=min(buc[d1[j]],d2[j]);
            }
        }
        for(int i=1;i<=cnt;i++)buc[d1[i]]=0x7f7f7f7f;
    }
    void solve(int k,int s){
        vst[k]=true,calc(k);
        for(int i=head[k];i;i=edge[i].nxt){
            int v=edge[i].to;
            if(vst[v])continue;
            root=0,allsiz=(siz[v]>siz[k]?s-siz[k]:siz[v]),getroot(v,0),solve(root,allsiz);
        }
    }
    int main(){
        maxx[0]=allsiz=n=read(),K=read(),memset(buc,127,sizeof(buc));
        for(int i=1;i<n;i++){
            int u=read()+1,v=read()+1,w=read();
            edge[++tot]=(Edge){v,head[u],w},head[u]=tot,edge[++tot]=(Edge){u,head[v],w},head[v]=tot;
        }
        getroot(1,0),solve(root,allsiz),printf("%d
    ",ans>=n?-1:ans);
        return 0;
    }
    [IOI2011]Race
  • 相关阅读:
    【持续更新】养成一些好的C++编程习惯,争做一个不让同事骂街的程序员
    Inno Setup界面美化
    QWebengineView页面不实时刷新的问题
    Qt封装窗口进dll须知
    Inno Setup打包工具
    【转载】排序方式整理(带演示GIF)
    MySQL遇见SELECT list is not in GROUP BY clause and contains nonaggre的问题
    JMeter测试TCP协议
    Win10微软拼音关闭Ctrl+Shift+B快捷键
    Hive 窗口函数使用(1)
  • 原文地址:https://www.cnblogs.com/JDFZ-ZZ/p/14227059.html
Copyright © 2011-2022 走看看