• bzoj2599 [IOI2011]Race


    题目描述:

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

    题解:

    用桶存一下,然后每次换边的时候更新答案+合并桶。

    代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define N 200050
    #define K 1000050
    const int inf = 0x3f3f3f3f;
    inline int rd()
    {
        int f=1,c=0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=10*c+ch-'0';ch=getchar();}
        return f*c;
    }
    int n,k,hed[N],cnt;
    struct EG
    {
        int to,nxt,v;
    }e[2*N];
    void ae(int f,int t,int v)
    {
        e[++cnt].to = t;
        e[cnt].nxt = hed[f];
        e[cnt].v = v;
        hed[f] = cnt;
    }
    int rt,sum,v[N],siz[N];
    int mrk[N];
    void get_rt(int u,int fa)
    {
        v[u]=0,siz[u]=1;
        for(int j=hed[u];j;j=e[j].nxt)
        {
            int to = e[j].to;
            if(mrk[to]||to==fa)continue;
            get_rt(to,u);
            siz[u]+=siz[to];
            if(siz[to]>v[u])v[u]=siz[to];
        }
        v[u] = max(v[u],sum-siz[u]);
        if(v[u]<v[rt])rt=u;
    }
    struct Pair{int x,d;}p[N];
    int tot;
    int g[K],ans=inf,max_dis;
    void dfs(int u,int fa,int dep,int dis)
    {
        if(dis>k)return ;
        if(dis==k)
        {
            ans = min(ans,dep);
            return ;
        }
        p[++tot].x = dep,p[tot].d = dis;
        max_dis=max(max_dis,dis);
        for(int j=hed[u];j;j=e[j].nxt)
        {
            int to = e[j].to;
            if(to==fa||mrk[to])continue;
            dfs(to,u,dep+1,dis+e[j].v);
        }
    }
    void work(int u)
    {
        mrk[u] = 1;int mx = 0;
        for(int j=hed[u];j;j=e[j].nxt)
        {
            int to = e[j].to;
            if(mrk[to])continue;
            max_dis=0;tot=0;
            dfs(to,u,1,e[j].v);
            mx = max(mx,max_dis);
            for(int i=1;i<=tot;i++)
                if(g[k-p[i].d]!=inf)
                    ans = min(ans,g[k-p[i].d]+p[i].x);
            for(int i=1;i<=tot;i++)
                if(g[p[i].d]>p[i].x)g[p[i].d]=p[i].x;
        }
        for(int i=1;i<=mx;i++)g[i]=inf;
        for(int j=hed[u];j;j=e[j].nxt)
        {
            int to = e[j].to;
            if(mrk[to])continue;
            rt=0,sum=siz[to];
            get_rt(to,0);
            work(rt);
        }
    }
    int main()
    {
        n = rd(),k = rd();
        for(int ff,tt,vv,i=1;i<n;i++)
        {
            ff = rd()+1,tt = rd()+1,vv = rd();
            ae(ff,tt,vv),ae(tt,ff,vv);
        }
        memset(g,0x3f,sizeof(g));
        v[0]=inf;
        rt=0,sum=n;
        get_rt(1,0);
        work(rt);
        printf("%d
    ",ans==inf?-1:ans);
        return 0;
    }
  • 相关阅读:
    1.2顺序表
    1.1数据结构
    Java 造假数据
    Python造假数据,用这个库
    真香 用这七大Python效率工具
    mybatis 详情
    MySQL 的 INSERT ··· ON DUPLICATE KEY UPDATE
    mysql之case when then 经典用法
    SELECT NOW(),CURDATE(),CURTIME()
    MySQL CONCAT_WS 函数
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10190063.html
Copyright © 2020-2023  润新知