其他分享
首页 > 其他分享> > LG P4149 [IOI2011]Race

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\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