Solution to the transportation plan of Luogu 2680

Keywords: less

Better blog viewing effect

Brief introduction

nnn point edge weight tree gives mmm key chains. The weight of an edge on the tree is changed to 0, so that the maximum value of the sum of mmm chains is the minimum. n,m<=1e5n,m<=1e5n,m<=1e5.

thinking

Binary maximum kkk. Now consider how to test a kkk.

Find all chains and chains > k > k > k, and set the longest chain length as SSS, with CCC chains. Find the edge covered by all CCC chains by tree chain segmentation. Set the edge weight to w w w. if S − w < = ks-w < = KS − w < = k, and because this edge is covered by all and > k > k > k chains, set the edge weight to 000, then correct all and > k > k > k chains. Then the condition is satisfied, and the test result is true.

And then the dichotomy is Ke.

How to find the edge covered by all chains

If you are wise enough, skip this part.

Open a temporary tree, all edge weights are 000, tree chain segmentation maintenance: for all and > k > k > k > k chains (a,b)(a,b)(a,b), the edge weights on the chain are + 1.

Then just find the edge with weight = C=C=C, that is to say.

But tree chain partition maintains point weight. How to convert edge weight into point weight? Just record the weight of an edge on the son of that edge. Then when we add the chain (u,v)(u,v)(u,v), remember to withdraw the operation of LCA(u,v)LCA(u,v)LCA(u,v) LCA (U, V), because this is multi calculation.

Code

#include <bits/stdc++.h>using namespace std;
namespace Flandre_Scarlet
{
    #define int long long 
    #define N 355555
    #define F(i,l,r) for(int i=l;i<=r;++i)
    #define D(i,r,l) for(int i=r;i>=l;--i)
    #define Fs(i,l,r,c) for(int i=l;i<=r;c)
    #define Ds(i,r,l,c) for(int i=r;i>=l;c)
    #define MEM(x,a) memset(x,a,sizeof(x))
    #define FK(x) MEM(x,0)
    #define Tra(i,u) for(int i=G.Start(u),__v=G.To(i);~i;i=G.Next(i),__v=G.To(i))
    #define p_b push_back
    #define sz(a) ((int)a.size())
    #define iter(a,p) (a.begin()+p)
    class Graph //chart
    {
        public:
            int head[N];
            int EdgeCount;
            struct Edge
            {
                int To,Label,Next;
            }Ed[N<<1];
            void clear(int _V=N,int _E=N<<1) 
            {
                memset(Ed,-1,sizeof(Edge)*(_E));
                memset(head,-1,sizeof(int)*(_V));
                EdgeCount=-1;
            }
            void AddEdge(int u,int v,int w=1)
            {
                Ed[++EdgeCount]=(Edge){v,w,head[u]};
                head[u]=EdgeCount;
            }
            void Add2(int u,int v,int w=1) {AddEdge(u,v,w);AddEdge(v,u,w);}
            int Start(int u) {return head[u];}
            int To(int u){return Ed[u].To;}
            int Label(int u){return Ed[u].Label;}
            int Next(int u){return Ed[u].Next;}
    }G;
    class BIT //Tree array
    {
        public:
            int tree[N];
            int len;
            void BuildTree(int _len)
            {
                len=_len;
                FK(tree);
            }
            void Add(int pos,int val=1)
            {
                for(int i=pos;i<=len;i+=(i&(-i)))
                {
                    tree[i]+=val;
                }
            }
            void RAdd(int l,int r,int val=1) {Add(l,val);Add(r+1,-val);}
            int Query(int pos)
            {
                int ans=0;
                for(int i=pos;i>0;i-=(i&(-i)))
                {
                    ans+=tree[i];
                }
                return ans;
            }
    }T;
    void R1(int &x)
    {
        x=0;char c=getchar();int f=1;
        while(c<'0' or c>'9') f=(c=='-')?-1:1,c=getchar();
        while(c>='0' and c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        x=(f==1)?x:-x;
    }
    int n,m;
    int a[N],b[N];
    void Input()
    {
        R1(n),R1(m);
        G.clear();
        int u,v,w;
        F(i,1,n-1) R1(u),R1(v),R1(w),G.Add2(u,v,w);
        F(i,1,m) R1(a[i]),R1(b[i]);
    }

    int fa[N],deep[N],size[N],dis[N];
    int son[N],val[N]; 
    //Val [i]: the edge right between I and fa[i], that is, "record the edge right on the son of this side"
    //dis[i]: i weighted distance to the root node (i.e. the sum of all edge weights passed)
    void DFS1(int u,int f)
    {
        fa[u]=f; 
        deep[u]=(u==f)?0:deep[f]+1;
        dis[u]=(u==f)?0:dis[f]+val[u]; 
        size[u]=1;
        son[u]=-1;int Max=-1;
        Tra(i,u)
        {int v=__v;
            if (v!=f)
            {
                val[v]=G.Label(i);
                DFS1(v,u);
                size[u]+=size[v];
                if (size[v]>Max) {Max=size[v];son[u]=v;}
            }
        }
    }
    int DFSid[N],top[N],Time=0;
    void DFS2(int u,int topu)
    {
        DFSid[u]=++Time;
        top[u]=topu;
        if (son[u]==-1) return;
        DFS2(son[u],topu);
        Tra(i,u)
        {int v=__v;
            if (v!=fa[u] and v!=son[u]) DFS2(v,v);
        }
    }
    int LCA(int u,int v) //Tree section for LCA (really just a LCA, nothing else)
    {
        while(top[u]!=top[v])
        {
            if (deep[top[u]]<deep[top[v]]) swap(u,v);
            u=fa[top[u]]; 
        }
        return deep[u]<deep[v]?u:v;
    }
    int PathLen(int u,int v){return dis[u]+dis[v]-2*dis[LCA(u,v)];} //Find the weighted length of chain < u, V >
    void PathAdd(int u,int v,int w=1)
    {
        while(top[u]!=top[v])
        {
            if (deep[top[u]]<deep[top[v]]) swap(u,v);
            T.RAdd(DFSid[top[u]],DFSid[u],w);
            u=fa[top[u]];
        }
        if (deep[u]>deep[v]) swap(u,v);
        T.RAdd(DFSid[u],DFSid[v],1); //General tree section operation

        int L=LCA(u,v);
        T.RAdd(DFSid[L],DFSid[L],-1); //Subtract the excess
    }
    int Maxlen;
    bool cxk(int k)
    {
        T.BuildTree(n);
        int cnt=0;
        F(i,1,m) if (PathLen(a[i],b[i])>k) //If the weight of this edge is too large
        {
            ++cnt;
            PathAdd(a[i],b[i],1);
        }
        
        F(i,1,n) 
        {
            if (T.Query(DFSid[i])==cnt and Maxlen-val[i]<=k) 
            // T.Query(DFSid[i])==cnt means that I and fa[i] are covered by all the modified edges
            //Maxlen Val [i] < K means that I can correct all the corrected edges
            {
                return true; //So at this time, set the weight of (i,fa[i]) to 0, and the condition is satisfied.
            }
        }
        return false;
    }
    void Soviet()
    {
        DFS1(1,1);
        DFS2(1,1);
        Maxlen=-1; F(i,1,m) Maxlen=max(Maxlen,PathLen(a[i],b[i])); //Maxlen k asked in advance, one m less
        T.BuildTree(n);
        int l=0,r=1e9; //Note: l=0 (this is what I wrote at the beginning, I haven't had WA, but I guess I can write l=1 with several points of WA)
        while(l<r)
        {
            int mid=(l+r)>>1;
            if (cxk(mid)) r=mid;
            else l=mid+1;
        }
        printf("%lld\n",l);
    }

    #define Flan void
    Flan IsMyWife()
    {
        Input();
        Soviet();
    }
    #undef int //long long 
}
int main(){
    Flandre_Scarlet::IsMyWife();
    getchar();getchar();
    return 0;
}
Published 210 original articles, won praise 8, visited 8911
Private letter follow

Posted by mentalfloss on Sat, 11 Jan 2020 06:03:42 -0800