zoukankan      html  css  js  c++  java
  • 洛谷 P3128 [USACO15DEC]最大流Max Flow

    题目描述

    Farmer John has installed a new system of  pipes to transport milk between the  stalls in his barn (), conveniently numbered . Each pipe connects a pair of stalls, and all stalls are connected to each-other via paths of pipes.

    FJ is pumping milk between  pairs of stalls (). For the th such pair, you are told two stalls  and , endpoints of a path along which milk is being pumped at a unit rate. FJ is concerned that some stalls might end up overwhelmed with all the milk being pumped through them, since a stall can serve as a waypoint along many of the  paths along which milk is being pumped. Please help him determine the maximum amount of milk being pumped through any stall. If milk is being pumped along a path from  to , then it counts as being pumped through the endpoint stalls  and

    , as well as through every stall along the path between them.

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

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

    输入输出格式

    输入格式:

    The first line of the input contains  and .

    The next  lines each contain two integers  and  () describing a pipe

    between stalls  and .

    The next  lines each contain two integers  and  describing the endpoint

    stalls of a path through which milk is being pumped.

    输出格式:

    An integer specifying the maximum amount of milk pumped through any stall in the

    barn.

    输入输出样例

    输入样例#1:
    5 10
    3 4
    1 5
    4 2
    5 4
    5 4
    5 4
    3 5
    4 3
    4 3
    1 3
    3 5
    5 4
    1 5
    3 4
    输出样例#1:
    9

    解题思路

    感谢洛谷里@j_william 指出我的错误,改正了重发一个。
    我之前并没有听说过树上差分这么高级的东东,于是为了练手速花了40min敲了一个树剖套线段树(蒟蒻码力不足),写好了线段树的一堆函数定义(maketree() pushdown() query() update()),剩着函数内部等待填充,感觉到一种绝望:还有那么多,要敲到啥时候啊。。。正在调整心态准备敲线段树时,突然想到,这题好像只是区间修改、单点查询?差分的树状数组!
    于是内心一片愉悦啊,愉快地敲完短得多的树状数组,顺利1A!
    正经的题解
    增加一条x到y的路径,就是把x到y的所有点的点权加1,很容易想到这是树剖板题的第一个操作,又由于这题只用单点查询,于是再套单点修改、区间查询的树状数组即可

    源代码 

    #include<bits/stdc++.h>
    #define lson(x) ((x)<<1)
    #define rson(x) (((x)<<1)|1)
    #define lowbit(x) (x)&(-(x))
    using namespace std;
    int n,k;
    struct Edge{
        int next,to;
    }e[100010];
    int cnt=1,head[50010];
    void add_e(int u,int v)
    {
        e[cnt].to=v;
        e[cnt].next=head[u];
        head[u]=cnt++;
    }
    struct tree{
        int fa;
        vector<int> son;
        int dep;
        int num_to;
        int wson;
        int top;
        int new_id;
    }t[50010];
    bool vis[50010];
    int dfs1(int u,int fa,int depth)
    {
        vis[u]=1;
        t[u].fa=fa;
        t[u].dep=depth;
        t[u].num_to=1;
        for(int i=head[u],weightest=-1,w;i;i=e[i].next)
        {
            int v=e[i].to;
            if(vis[v]) continue;
            t[u].son.push_back(v);
            w=dfs1(v,u,depth+1);
            if(w>weightest)
            {
                t[u].wson=v;
                weightest=w;
            }
            t[u].num_to+=w;
        }
        return t[u].num_to;
    }
    int num_id=1;
    void dfs2(int u,int top)
    {
        t[u].top=top;
        t[u].new_id=num_id++;
        int sz=t[u].son.size();
        if(sz==0)
            return;
        dfs2(t[u].wson,top);
        for(int i=0;i<sz;i++)
        {
            int v=t[u].son[i];
            if(v==t[u].wson) continue;
            dfs2(v,v);
        }
    }
    int s[50010]={0};
    void add(int node,int w)
    {
        while(node<=n)//就是这里错了,我原来的题解没写'=',数据水没被卡,,,
        {
            s[node]+=w;
            node+=lowbit(node);
        }
    }
    int ask(int node)
    {
        int ans=0;
        while(node)
        {
            ans+=s[node];
            node-=lowbit(node);
        }
        return ans;
    }
    void up(int x,int y)//////////////////////////////////////
    {
        while(t[x].top!=t[y].top)//x向y上靠 即y.top 更高 
        {
            if(t[t[x].top].dep<t[t[y].top].dep) swap(x,y);
            add(t[x].new_id-1,-1);
            add(t[t[x].top].new_id,1);
            x=t[t[x].top].fa;
        }
        if(t[x].new_id>t[y].new_id) swap(x,y);
        add(t[x].new_id,1);
        add(t[y].new_id+1,-1);
    }
    int main()
    {
        scanf("%d%d",&n,&k);
        for(int i=1,x,y;i<n;i++)
        {
            scanf("%d%d",&x,&y);
            add_e(x,y);
            add_e(y,x);
        }
        dfs1(1,1,1);
        dfs2(1,1);
        for(int i=0,x,y;i<k;i++)
        {
            scanf("%d%d",&x,&y);
            up(x,y);
        }
        int maxn=s[1];
        for(int i=2;i<=n+1;i++)//还有这里,我不知道当时咋想的,写了个i<=50001
        {
            maxn=max(maxn,ask(i));
        }
        printf("%d",maxn);
        return 0;
    }
  • 相关阅读:
    简述智障版本搜索引擎架构
    kaggle PredictingRedHatBusinessValue 简单的xgboost的交叉验证
    机器学习速查表
    World final 2017 题解
    微博爬虫
    喵哈哈村的魔法考试 Round #21 (Div.2) 题解
    喵哈哈村的魔法考试 Round #20 (Div.2) 题解
    Tinkoff Challenge
    常用的机器学习&数据挖掘知识(点)总结
    喵哈哈村的魔法考试 Round #19 (Div.2) 题解
  • 原文地址:https://www.cnblogs.com/wawcac-blog/p/6869850.html
Copyright © 2011-2022 走看看