zoukankan      html  css  js  c++  java
  • [USACO15DEC]最大流Max Flow(树链剖分,线段树)

    FJ给他的牛棚的N(2≤N≤50,000)个隔间之间安装了N-1根管道,隔间编号从1到N。所有隔间都被管道连通了。

    FJ有K(1≤K≤100,000)条运输牛奶的路线,第i条路线从隔间si运输到隔间ti。一条运输路线会给它的两个端点处的隔间以及中间途径的所有隔间带来一个单位的运输压力,你需要计算压力最大的隔间的压力是多少。

    思路:

    比较基础的树剖题

    对于每条线路

    我们维护一个区间最大值的线段树

    通过树剖实现每个加1的操作

    最后读取总最大值就好

    代码:

    // luogu-judger-enable-o2
    #include<iostream>
    #include<cstdio>
    #define rii register int i
    #define rij register int j
    using namespace std;
    int fa[50005],top[50005],size[50005],nid[50005];
    int head[50005],n,k,bnt,cnt,sd[50005],wes[50005];
    struct ljb{
        int to,nxt;
    }y[100005];
    struct tree{
        int maxn,lazy;
    }x[800005];
    inline int rd(){
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)) {f=ch=='-'?0:1;ch=getchar();}
        while(isdigit(ch))  {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        return f?x:-x;
    }
    inline void add(int from,int to)
    {
        bnt++;
        y[bnt].to=to;
        y[bnt].nxt=head[from];
        head[from]=bnt;
    }
    inline void pushdown(int bh)
    {
        x[bh*2].lazy+=x[bh].lazy;
        x[bh*2].maxn+=x[bh].lazy;
        x[bh*2+1].lazy+=x[bh].lazy;
        x[bh*2+1].maxn+=x[bh].lazy;
        x[bh].lazy=0;
    }
    void addjl(int l,int r,int nl,int nr,int bh)
    {
        if(l<nl)
        {
            l=nl;
        }
        if(r>nr)
        {
            r=nr;
        }
        if(l==nl&&r==nr)
        {
            x[bh].lazy++;
            x[bh].maxn++;
            return;
        }
        if(x[bh].lazy!=0)
        {
            pushdown(bh);
        }
        int mid=(nl+nr)/2;
        if(l<=mid)
        {
            addjl(l,r,nl,mid,bh*2);
        }
        if(r>mid)
        {
            addjl(l,r,mid+1,nr,bh*2+1);
        }
        x[bh].maxn=max(x[bh*2].maxn,x[bh*2+1].maxn);
    }
    void dfs1(int wz,int nfa,int nsd)
    {
        fa[wz]=nfa;
        sd[wz]=nsd;
        size[wz]=1;
        int maxn=0;
        for(rii=head[wz];i!=0;i=y[i].nxt)
        {
            int to=y[i].to;
            if(to!=nfa)
            {
                dfs1(to,wz,nsd+1);
                size[wz]+=size[to];
                if(size[to]>maxn)
                {
                    wes[wz]=to;
                    maxn=size[to];
                }
            }
        }
    }
    void dfs2(int wz,int ntop)
    {
        cnt++;
        nid[wz]=cnt;
        top[wz]=ntop;
        if(wes[wz]==0)
        {
            return;
        }
        dfs2(wes[wz],ntop);
        for(rii=head[wz];i!=0;i=y[i].nxt)
        {
            int to=y[i].to;
            if(wes[wz]!=to&&fa[wz]!=to)
            {
                dfs2(to,to);
            }
        }
    }
    void addlj(int from,int to)
    {
        while(top[from]!=top[to])
        {
            if(sd[top[from]]<sd[top[to]])
            {
                swap(from,to);
            }
            addjl(nid[top[from]],nid[from],1,n,1);
            from=fa[top[from]];
        }
        if(sd[from]>sd[to])
        {
            swap(from,to);
        }
        addjl(nid[from],nid[to],1,n,1);
        from=fa[top[from]];
    }
    int main()
    {
    //    freopen("1.in","r",stdin);
    //    freopen("1.out","w",stdout);
        n=rd(),k=rd();
        for(rii=1;i<n;i++)
        {
            int from,to;
            from=rd(),to=rd();
            add(from,to);
            add(to,from);
        }
        dfs1(1,0,0);
        dfs2(1,1);
        for(rii=1;i<=k;i++)
        {
            int from,to;
            from=rd(),to=rd();
            addlj(from,to);
        }
        cout<<x[1].maxn;
    }
  • 相关阅读:
    用Java随机生成四则运算
    初涉猎软件工程的一些疑问
    201671010124 2016-2017-2 《Java程序设计》
    201671010124 2016-2017-2 《Java程序设计》2
    201671010124 2016-2017-2 《Java程序设计》初见Java
    《贪吃蛇》局部刷新法(C语言,字符界面)
    简单的《贪吃蛇》全局刷新法(C语言,字符界面)
    读取本地的json文件
    js获取当前页面的URL并且截取?之后的数据,返回json
    全面实用的Tab切换
  • 原文地址:https://www.cnblogs.com/ztz11/p/9926215.html
Copyright © 2011-2022 走看看