• 洛谷P4149 [IOI2011]Race(点分治)


    题目描述

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

    输入输出格式

    输入格式:

     

    第一行:两个整数 n,kn,k 。

    第二至 nn 行:每行三个整数,表示一条无向边的两端和权值 (注意点的编号从 00 开始)。

     

    输出格式:

     

    一个整数,表示最小边数量。

    如果不存在这样的路径,输出 -11 。

     

    输入输出样例

    输入样例#1: 
    4 3
    0 1 1
    1 2 2
    1 3 4
    输出样例#1: 
    2

    说明

    nle 200000,Kle 1000000n200000,K1000000 。

    题解:谁说点分一定要套容斥的?

    这题的暴力思路大约跟dp有点像,每次爆枚到一棵子树中每一个点的距离,显然对于这些距离di,能与他产生解的是之前所有子树中到达距离为k-di的点的最小深度。

    然后就是一遍dfs爆枚所有点,再一遍dfs更新所有最小深度,然后就可以a掉了

    代码如下:

    #include<map>
    #include<set>
    #include<queue>
    #include<cmath>
    #include<cstdio>
    #include<string>
    #include<vector>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define mp make_pair
    #define pii pair<int,int>
    #define inf 0x3f3f3f3f
    using namespace std;
    #define int ll
    typedef long long ll;
    int n,k,deep[2000010],dis[2000010],size[2000010],fa[2000010],vis[2000010];
    int tmp[10000010],ans;
    vector<pii> g[2000100];
    
    void get_size(int now,int f)
    {
        size[now]=1;
        fa[now]=f;
        for(int i=0; i<g[now].size(); i++)
        {
            if(vis[g[now][i].first]||g[now][i].first==f) continue;
            get_size(g[now][i].first,now);
            size[now]+=size[g[now][i].first];
        }
    }
    
    int get_zx(int now,int f)
    {
        if(size[now]==1) return now;
        int son,maxson=-1;
        for(int i=0; i<g[now].size(); i++)
        {
            if(vis[g[now][i].first]||g[now][i].first==f) continue;
            if(size[g[now][i].first]>maxson)
            {
                maxson=size[g[now][i].first];
                son=g[now][i].first;
            }
        }
        int zx=get_zx(son,now);
        while(size[zx]<2*(size[now]-size[zx])) zx=fa[zx];
        return zx;
    }
    
    void calc(int now,int f,int dep,int di)
    {
        deep[now]=dep;
        dis[now]=di;
        if(dis[now]<=k) ans=min(ans,tmp[k-dis[now]]+deep[now]);
        else return;
        for(int i=0; i<g[now].size(); i++)
        {
            if(vis[g[now][i].first]||g[now][i].first==f) continue;
            calc(g[now][i].first,now,dep+1,di+g[now][i].second);
        }
    }
    
    void dfs(int now,int f,int kd)
    {
        if(kd) tmp[dis[now]]=min(tmp[dis[now]],deep[now]);
        else tmp[dis[now]]=inf;
        for(int i=0;i<g[now].size();i++)
        {
            if(vis[g[now][i].first]||g[now][i].first==f) continue;
            dfs(g[now][i].first,now,kd);
        }
    }
    
    void solve(int now)
    {
        vis[now]=1;
        tmp[0]=0;
        for(int i=0;i<g[now].size();i++)
        {
            if(vis[g[now][i].first]) continue;
            calc(g[now][i].first,0,1,g[now][i].second);
            dfs(g[now][i].first,0,1);
        }
        for(int i=0;i<g[now].size();i++)
        {
            if(vis[g[now][i].first]) continue;
            dfs(g[now][i].first,0,0);
        }
        for(int i=0;i<g[now].size();i++)
        {
            if(vis[g[now][i].first]) continue;
            get_size(g[now][i].first,0);
            int zx=get_zx(g[now][i].first,0);
            solve(zx);
        }
    }
    
    main()
    {
        scanf("%lld%lld",&n,&k);
        for(int i=1;i<n;i++)
        {
            int from,to,cost;
            scanf("%lld%lld%lld",&from,&to,&cost);
            g[from+1].push_back(mp(to+1,cost));
            g[to+1].push_back(mp(from+1,cost));
        }
        ans=inf;
        memset(tmp,0x3f,sizeof(tmp));
        solve(1);
        ans==0x3f3f3f3f?puts("-1"):printf("%lld
    ",ans);
    }
  • 相关阅读:
    <置顶>Eclipse和myeclipse常用快捷键-操作-设置
    Eclipse : Loading descriptor for ...错误解决
    ORA-00937: 不是单组分组函数
    An error has occurred,See error log for more details 错误解决办法
    [Error Code: 942, SQL State: 42000] ORA-00942: 表或视图不存在
    ORA-00001: 违反唯一约束条件
    eclipse 出现user operation is waiting
    [空格][空白][特殊]字符/文字
    powerdesigner16.5安装教程及破解步骤
    mybatis遇到日期类型数据时String到date的转化
  • 原文地址:https://www.cnblogs.com/stxy-ferryman/p/9432824.html
Copyright © 2020-2023  润新知