和Leo一起做爱树上结构的好孩子之点分治 [IOI2011]Race

版权声明:LeoJAM Presents https://blog.csdn.net/fcb_x/article/details/82807717

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

点分治:

维护到这个值的最少步数

但是这个就只能一个子树一个子树的更新了

然后memset历史代价一定会TLE

所以再DFS一遍清除历史代价

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
typedef int INT;
#define int long long
const int INF=1e9+7;
const int N=2e5+100;
struct Front_star{
    int u,v,w,nxt;
}e[N<<1];
int cnt=0;
int first[N];
void add(int u,int v,int w){
    cnt++;
    e[cnt].u=u;
    e[cnt].v=v;
    e[cnt].w=w;
    e[cnt].nxt=first[u];
    first[u]=cnt;
}
//
int n,K;
int root=0;
int All;
int siz[N];
int dep[N];
int vis[N];
int F[N];
int d[1000100];
int c[N];
int ans;
inline void Get_Root(int u,int fat){
    siz[u]=1;
    int now=0;
    for(int i=first[u];i;i=e[i].nxt){
        int v=e[i].v;
        if(v==fat||vis[v])continue;
        Get_Root(v,u);
        siz[u]+=siz[v];
        if(now<siz[v])now=siz[v];
    }
    if(All-siz[u]>now)now=All-siz[u];
    F[u]=now;
    if(F[root]>now)root=u;
}
inline void Solve(int u,int fat){
    if(dep[u]<=K)ans=min(ans,d[K-dep[u]]+c[u]);
    for(int i=first[u];i;i=e[i].nxt){
        int v=e[i].v;
        if(vis[v]||v==fat)continue;
        dep[v]=dep[u]+e[i].w;
        c[v]=c[u]+1;
        Solve(v,u);
    }
}
inline void Update(int u,int fat){
    if(dep[u]<=K)d[dep[u]]=min(d[dep[u]],c[u]);
    for(int i=first[u];i;i=e[i].nxt){
        int v=e[i].v;
        if(v==fat||vis[v])continue;
        Update(v,u);
    }
}
inline void recover(int u,int fat){
    if(dep[u]<=K)d[dep[u]]=INF;
    for(int i=first[u];i;i=e[i].nxt){
        int v=e[i].v;
        if(v==fat||vis[v])continue;
        recover(v,u);
    }
}
inline void DFS(int u){
    d[0]=0;
    vis[u]=1;
    for(int i=first[u];i;i=e[i].nxt){
        int v=e[i].v;
        if(vis[v])continue;
        dep[v]=e[i].w;
        c[v]=1;
        Solve(v,u);
        Update(v,u);
    }
    for(int i=first[u];i;i=e[i].nxt){
        int v=e[i].v;
        if(vis[v])continue;
        recover(v,u);
    }
    for(int i=first[u];i;i=e[i].nxt){
        int v=e[i].v;
        if(vis[v])continue;
        All=siz[v];
        root=0;
        Get_Root(v,0);
        DFS(root);
    }
}
INT main(){
    F[0]=1e9+7;
//	freopen("test.in","r",stdin);
    scanf("%lld%lld",&n,&K);
    for(int i=1;i<=K;++i)d[i]=INF;
    for(int i=1;i<n;++i){
        int u,v,w;
        scanf("%lld%lld%lld",&u,&v,&w);
        ++u;
        ++v;
        add(u,v,w);
        add(v,u,w);
    }
    All=n;
    ans=INF;
    root=0;
    Get_Root(1,0);
    DFS(root);
    if(ans==INF)cout<<-1;
    else cout<<ans;
}

猜你喜欢

转载自blog.csdn.net/fcb_x/article/details/82807717