洛谷 P3128 [USACO15DEC]最大流Max Flow

简介: 题目描述 Farmer John has installed a new system of  pipes to transport milk between the  stalls in his barn (), conveniently numbered .

题目描述

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;
}

 

相关实践学习
部署Stable Diffusion玩转AI绘画(GPU云服务器)
本实验通过在ECS上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。
目录
相关文章
|
11月前
|
算法
poj 2479 Maximum sum(求最大子段和的延伸)
看完最大连续子段和 的 dp算法 这个很容易理解,我用dplift[i]保存第1到第i个之间的最大子段和,dpright[i]保存第i到第n个之间的最大子段和,最终结果就是dplift[i]+dpright[i+1]中最大的一个。
43 0
【PTA】7-8 到底有多二 (15分)
【PTA】7-8 到底有多二 (15分)
2205 0
P1216 [USACO1.5][IOI1994]数字三角形 Number Triangles
P1216 [USACO1.5][IOI1994]数字三角形 Number Triangles
PTA 7-4 胖达与盆盆奶 (20 分)
俗称“胖达”,会排队吃盆盆奶。它们能和谐吃奶的前提,是它们认为盆盆奶的分配是“公平”的,即:更胖的胖达能吃到更多的奶,等胖的胖达得吃到一样多的奶。
168 0
|
测试技术
PTA 1039 到底买不买 (20 分)
小红想买些珠子做一串自己喜欢的珠串。卖珠子的摊主有很多串五颜六色的珠串,但是不肯把任何一串拆散了卖。
111 0
L1-057 PTA使我精神焕发 (5 分)
L1-057 PTA使我精神焕发 (5 分)
86 0
L1-057 PTA使我精神焕发 (5 分)
PTA 7-1 多二了一点 (15 分)
若一个正整数有 2n 个数位,后 n 个数位组成的数恰好比前 n 个数位组成的数多 2,则称这个数字“多二了一点”。
113 0
PTA 1046 划拳 (15 分)
划拳是古老中国酒文化的一个有趣的组成部分。酒桌上两人划拳的方法为:每人口中喊出一个数字,同时用手比划出一个数字。
97 0
PTA 1088 三人行 (20 分)
子曰:“三人行,必有我师焉。择其善者而从之,其不善者而改之。”
83 0