ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

LG P4149 [IOI2011]Race

2021-01-05 07:32:31  阅读:207  来源: 互联网

标签:LG cnt 200005 int IOI2011 edge Race buc include


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\n",ans>=n?-1:ans);
    return 0;
}
[IOI2011]Race

标签:LG,cnt,200005,int,IOI2011,edge,Race,buc,include
来源: https://www.cnblogs.com/JDFZ-ZZ/p/14227059.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有