• [BZOJ 2599&COGS 2648][IOI2011]Race(点分治)


    Description

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

    Solution

    点分~g[i]存当前的子树中边权和为i的最小边数,h[i]存之前的子树中边权和为i的最小边数

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<vector>
    #define INF 0x3f3f3f3f
    #define N 200005
    #define K 1000005
    typedef long long LL;
    using namespace std;
    int n,k,ans=INF,mx,tot=0,root=0,tim=0,sign[K],g[K],h[K],vis[N],siz[N],maxv[N],head[N],cnt=0;
    vector<int>V;
    int read()
    {
        int x=0,f=1;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    struct Node
    {
        int next,to,w;
    }Edges[N*2];
    void addedge(int u,int v,int w)
    {
        Edges[cnt].next=head[u];
        head[u]=cnt;
        Edges[cnt].to=v;
        Edges[cnt++].w=w;
    }
    void getroot(int u,int f)
    {
        siz[u]=1,maxv[u]=0;
        for(int i=head[u];~i;i=Edges[i].next)
        {
             int v=Edges[i].to;
            if(vis[v]||v==f)continue;
            getroot(v,u);
            siz[u]+=siz[v],maxv[u]=max(maxv[u],siz[v]);
        }
        maxv[u]=max(maxv[u],tot-siz[u]);
        if(maxv[u]<maxv[root])root=u;
    }
    void getdeep(int u,int f,int d,int c)
    {
        if(d>k)return;
        mx=max(mx,d);
        if(sign[d]!=tim)g[d]=c,sign[d]=tim,V.push_back(d);
        else g[d]=min(g[d],c);
        for(int i=head[u];~i;i=Edges[i].next)
        {
            int v=Edges[i].to;
            if(vis[v]||v==f)continue;
            getdeep(v,u,d+Edges[i].w,c+1);
        }
    }
    void work(int u)
    {
        vis[u]=1,h[0]=0,mx=0;
        for(int i=head[u];~i;i=Edges[i].next)
        {
            int v=Edges[i].to;
            if(vis[v])continue;
            V.clear();
            tim++,getdeep(v,u,Edges[i].w,1);
            for(int j=0;j<V.size();j++)
            {int t=V[j];ans=min(ans,g[t]+h[k-t]);}
            for(int j=0;j<V.size();j++)
            {int t=V[j];h[t]=min(h[t],g[t]);}
        }
        for(int j=0;j<=mx;j++)h[j]=INF;
        for(int i=head[u];~i;i=Edges[i].next)
        {
            int v=Edges[i].to;
            if(vis[v])continue;
            root=0,tot=siz[v];
            getroot(v,u),work(root);
        }
    }
    int main()
    {
        n=read(),k=read();
        memset(h,0x3f,sizeof(h));
        memset(head,-1,sizeof(head));
        for(int i=1;i<n;i++)
        {
            int u=read()+1,v=read()+1,w=read();
            addedge(u,v,w),addedge(v,u,w);
        }
        maxv[0]=INF,tot=n;
        getroot(1,0),work(root);
        printf("%d
    ",ans==INF?-1:ans);
        return 0;
    }
  • 相关阅读:
    ADO.NET中DataSet的应用(读书笔记5)
    ADO.NET中DataTable的应用(读书笔记4)
    如何在前端界面操作数据表(读书笔记3)
    如何在各类空间中输入输出数据(读书笔记2)
    关于利用input的file属性在页面添加图片的问题
    本地存储
    react
    微信开发
    node
    SVN和GIT
  • 原文地址:https://www.cnblogs.com/Zars19/p/6942035.html
Copyright © 2020-2023  润新知