[洛谷P4149][IOI2011]Race:点分治

分析:

先计算完毕当前重心的答案再往下递归。

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int MAXN=200005;
const int MAXK=1000005;
inline LL read(){
    LL x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return x*f;
}
int n,un,cog,head[MAXN],ecnt,mincnt[MAXK],rcnt[MAXK],siz[MAXN],stack[MAXN],top,ans=0x3f3f3f3f;
LL k;
bool vis[MAXN];
struct Edge{
    int to,nxt;LL w;
}e[MAXN<<1];
inline void add_edge(int bg,int ed,int val){
    ecnt++;
    e[ecnt].to=ed;
    e[ecnt].nxt=head[bg];
    e[ecnt].w=val;
    head[bg]=ecnt;
}
void dfs1(int x,int pre,int depth,LL len){
    siz[x]=1;if(len<=k) rcnt[len]=min(rcnt[len],depth),stack[++top]=len;
    for(int i=head[x];i;i=e[i].nxt){
        int ver=e[i].to;
        if(vis[ver]||ver==pre) continue;
        dfs1(ver,x,depth+1,len+e[i].w);
        siz[x]+=siz[ver];
    }
}
void dfs2(int x,int pre){
    bool flag=0;
    for(int i=head[x];i;i=e[i].nxt){
        int ver=e[i].to;
        if(vis[ver]||ver==pre) continue;
        if(siz[ver]>un/2) flag=1;
        dfs2(ver,x);
        if(cog!=-1) return;
    }
    if(un-siz[x]>un/2) flag=1;
    if(!flag){
        cog=x;
        return;
    }   
}
void solve(int x){
    mincnt[0]=0,vis[x]=1,top=0;int pretop=0,nowtop=0;
    for(int i=head[x];i;i=e[i].nxt){
        int ver=e[i].to;
        if(vis[ver]) continue;
        dfs1(ver,x,1,e[i].w);
        for(int j=pretop+1;j<=top;j++) ans=min(ans,rcnt[stack[j]]+mincnt[k-stack[j]]);
        nowtop=top;
        while(top!=pretop){
            mincnt[stack[top]]=min(mincnt[stack[top]],rcnt[stack[top]]);
            rcnt[stack[top--]]=0x3f3f3f3f;
        }
        pretop=top=nowtop;
    }
    while(top) mincnt[stack[top--]]=0x3f3f3f3f;
    for(int i=head[x];i;i=e[i].nxt){
        int ver=e[i].to;
        if(vis[ver]) continue;
        un=siz[ver],cog=-1;dfs2(ver,x);
        solve(cog);
    }
}
int main(){
    n=read(),k=read();
    for(int i=1;i<n;i++){
        int u=read(),v=read();LL w=read();
        add_edge(u,v,w);
        add_edge(v,u,w);
    }
    top=0;dfs1(0,-1,0,0);
    memset(rcnt,0x3f,sizeof rcnt);
    memset(mincnt,0x3f,sizeof mincnt);
    top=0;
    un=n;dfs2(0,-1);
    solve(cog);
    if(ans<1e9) printf("%d\n",ans);
    else printf("-1\n");
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/ErkkiErkko/p/9483579.html
今日推荐