洛谷P3128 [USACO15DEC]最大流Max Flow
题目描述
Farmer John has installed a new system of N−1 pipes to transport milk between the N stalls in his barn (2≤N≤50,000), conveniently numbered 1…N. Each pipe connects a pair of stalls, and all stalls are connected to each-other via paths of pipes.
FJ is pumping milk between KK pairs of stalls (1≤K≤100,000). For the iith such pair, you are told two stalls s_isiand t_iti, 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 KK 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 si to ti, then it counts as being pumped through the endpoint stalls si and
ti, 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 N and K.
The next N−1 lines each contain two integers x and y (x≠y) describing a pipe
between stalls x and y.
The next K lines each contain two integers ss and tt 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.
输入输出样例
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
9
/*
做这道题还是为了做运输计划这题 学学树上差分啥的
虽然名字叫做最大流 但是用不上网络流的知识啊 可以说是树上差分点修改的模板题了(貌似暴力也可,但时间复杂度肯定不优) 记录每一个点访问的次数,维护一个差分数组f 设s为起点 t为终点 则f[s]++ f[t]++ f[lca]-- f[fa[lca]]-- 具体为什么洛谷日报写的很详细了 https://rpdreamer.blog.luogu.org/ci-fen-and-shu-shang-ci-fen */ #include <bits/stdc++.h> using namespace std; const int MAXN = 50010; int deep[MAXN],f[MAXN][25],lg[MAXN],head[MAXN],cnt; int n,m,s,ans,ppt[MAXN]; struct node{ int to,pre; }G[MAXN<<2]; void add(int from,int to){ G[++cnt].to = to; G[cnt].pre = head[from]; head[from] = cnt; } inline int read() { int x = 0,m = 1; char ch; while(ch < '0' || ch > '9') {if(ch == '-') m = -1;ch = getchar();} while(ch >= '0' && ch <= '9'){x = x*10+ch-'0';ch=getchar();} return m * x; }//读入优化哦 inline void dfs1(int u) { for(int i = head[u];i;i = G[i].pre) { int v = G[i].to; if(v != f[u][0]) { f[v][0] = u; deep[v] = deep[u] + 1; dfs1(v); } } }//处理LCA inline int lca(int u,int v) { if(deep[u] < deep[v]) swap(u,v); int dis = deep[u] - deep[v]; for(register int i = 0;i <= lg[n];i++) { if((1 << i) & dis) u = f[u][i]; } if(u == v) return u; for(register int i = lg[deep[u]];i >= 0;i--) { if(f[u][i] != f[v][i]) { u = f[u][i];v = f[v][i]; } } return f[u][0]; }//倍增LCA inline void init() { for(register int i = 1;i <= n;i++) { lg[i] = lg[i-1] + (1 << lg[i-1] + 1 == i); } for(register int j = 1;j <= lg[n];j++) { for(register int i = 1;i <= n;i++) { if(f[i][j-1] != -1) f[i][j] = f[f[i][j-1]][j-1]; } } }//初始化 inline void dfs2(int u,int fa){ for(int i = head[u];i;i = G[i].pre){ int v = G[i].to; if(v == fa) continue; dfs2(v,u); ppt[u] += ppt[v]; } ans = max(ans,ppt[u]); }//把差分数组加回去(前缀和?) int main() { int x,y; n = read();m = read(); for(register int i = 1;i <= n-1;i++) { x = read();y = read(); add(x,y);add(y,x);//树要双向加边 } dfs1(1); init(); for(int i = 1;i <= m;i++){ x = read();y = read(); int Lca = lca(x,y); ppt[x]++,ppt[y]++,ppt[Lca]--,ppt[f[Lca][0]]--;//树上差分 不多说 } dfs2(1,0); printf("%d\n",ans); return 0; }