P4149 [IOI2011]Race(dsu 做法)

题:https://www.luogu.com.cn/problem/P4149

题意:找出树上点对距离恰好为k的点对,且点对之间的距离最小,要是不存在输出-1;

分析:对于每次的dfs的每次u,对于u的每一个孩子v,先计数路径,再把v的子树含的路径更新到桶里

#include<bits/stdc++.h>
#include<tr1/unordered_map>
using namespace std;
typedef long long ll;
#define pb push_back
const int M=2e5+5;
const int inf=0x3f3f3f3f;
struct node{
    int v;
    ll w;
};
vector<node>g[M];
unordered_map<ll,ll>mp;
ll ans,n;
ll k;
ll sz[M],deep[M],son[M],vis[M];
ll dis[M];
void dfs1(int u,int fa){
    sz[u]=1;
    deep[u]=deep[fa]+1;
    for(auto i:g[u]){
        int v=i.v;
        ll w=i.w;
        if(v!=fa){
            dis[v]=dis[u]+w;
            dfs1(v,u);
            sz[u]+=sz[v];
            if(sz[son[u]]<sz[v])
                son[u]=v;
        }
    }
}
void cal(int u,int fa,int root){
    ll tmp=k-dis[u]+2*dis[root];
    if(mp[tmp]){
        ans=min(ans,mp[tmp]+deep[u]-2*deep[root]);
    }
    for(auto i:g[u]){
        int v=i.v;
        if(v!=fa&&!vis[v])
            cal(v,u,root);
    }
}
void update(int u,int fa,int p){

    if(p==1){
        if(mp[dis[u]]==0)
            mp[dis[u]]=deep[u];
        else
            mp[dis[u]]=min(mp[dis[u]],deep[u]);
    }
    else
        mp[dis[u]]=0;
    for(auto i:g[u]){
        int v=i.v;
        if(v!=fa&&!vis[v])
            update(v,u,p);
    }

}
void dfs2(int u,int fa,int sign){
    for(auto i:g[u]){
        int v=i.v;
        if(v!=fa&&v!=son[u])
            dfs2(v,u,0);
    }
    if(son[u])
        dfs2(son[u],u,1),vis[son[u]]=1;
    for(auto i:g[u]){
        int v=i.v;
        if(v!=fa&&!vis[v]){
            cal(v,u,u);
            update(v,u,1);
        }
    }
    if(mp[dis[u]]==0)
        mp[dis[u]]=deep[u];
    else
        mp[dis[u]]=min(mp[dis[u]],deep[u]);
    if(mp[dis[u]+k])
        ans=min(ans,mp[dis[u]+k]-deep[u]);

    if(son[u])
        vis[son[u]]=0;
    if(!sign)
        update(u,fa,0),mp[dis[u]]=0;

}
int main(){
    scanf("%lld%lld",&n,&k);
    for(int i=1;i<n;i++){
        int u,v;
        ll w;
        scanf("%d%d%lld",&u,&v,&w);
        u++,v++;
        g[u].pb(node{v,w});
        g[v].pb(node{u,w});
    }
    dfs1(1,0);
    ans=inf;
    dfs2(1,0,0);
    if(ans==inf)
        puts("-1");
    else
        printf("%d\n",ans);
    return 0;
}
/**
4 3
0 1 1
1 2 2
1 3 4


*/
View Code

 

posted @ 2020-04-10 21:26  starve_to_death  阅读(236)  评论(2编辑  收藏  举报