七台河市网站建设_网站建设公司_展示型网站_seo优化
2026/1/22 9:57:53 网站建设 项目流程

【题目来源】
https://www.luogu.com.cn/problem/P3128

【题目描述】
Farmer John 在他的谷仓中安装了 N-1 条管道,用于在 N 个牛棚之间运输牛奶(2≤N≤50000),牛棚方便地编号为 1...N。每条管道连接一对牛棚,所有牛棚通过这些管道相互连接。
FJ 正在 K 对牛棚之间泵送牛奶(1≤K≤100000)。对于第 i 对牛棚,你被告知两个牛棚 si 和 ti,这是牛奶以单位速率泵送的路径的端点。FJ 担心某些牛棚可能会因为过多的牛奶通过它们而不堪重负,因为一个牛棚可能会作为许多泵送路径的中转站。请帮助他确定通过任何一个牛棚的最大牛奶量。如果牛奶沿着从 si 到 ti 的路径泵送,那么它将被计入端点牛棚 si 和 ti,以及它们之间路径上的所有牛棚。

【输入格式】
输入的第一行包含 N 和 K。
接下来的 N-1 行每行包含两个整数 x 和 y(x≠y),描述连接牛棚 x 和 y 的管道。
接下来的 K 行每行包含两个整数 s 和 t,描述牛奶泵送路径的端点牛棚。

【输出格式】
输出一个整数,表示通过谷仓中任何一个牛棚的最大牛奶量。

【输入样例】
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

【数据范围】
2≤N≤5×10^4,1≤K≤10^5。

【算法分析】
● 树上差分
树上差分是一种在树上高效处理路径修改和查询的算法技巧,核心思想是将路径操作转化为对节点差分数组的单点修改,最后通过一次遍历还原出结果。 它特别适合处理‌多次对树上路径进行加减操作,最后查询某个点或边的权值‌这类问题。
(一)核心思想
点差分‌:对路径 (x, y) 上所有点的权值进行修改。通过在 x 和 y 处 +val,在 lca(x,y) 和其父节点处 -val,最后通过 DFS 自底向上求和即可还原路径上的权值。具体操作为:对路径 (x, y) 加 val,执行 diff[x] += val, diff[y] += val, diff[lca] -= val, diff[fa[lca]] -= val。
边差分‌:对路径 (x, y) 上所有边的权值进行修改。通常将边权下放给深度较大的子节点,转化为点权问题,处理方式与点差分类似。具体操作为:对路径 (x, y) 加 val,执行 diff[x] += val, diff[y] += val, diff[lca] -= 2 * val(假设边权下放给子节点)。
(二)适用场景
点差分‌:路径点权修改、子树点权修改、查询点权。
边差分‌:路径边权修改、查询边权。
(三)与其他算法对比
与线段树对比‌:树上差分代码简洁,适合离线操作;线段树支持在线查询,但常数较大。
与树链剖分对比‌:树上差分处理路径修改更高效;树链剖分功能更强大,支持复杂路径查询。

● LCA ← 树上差分常用 LCA
(1)暴力法(向上标记法):https://blog.csdn.net/hnjzsyjyj/article/details/152026341
(2)暴力法(同步前进法‌):https://blog.csdn.net/hnjzsyjyj/article/details/152070927
(3)倍增法(DFS预处理):https://blog.csdn.net/hnjzsyjyj/article/details/152203103
(4)倍增法(BFS预处理):​​​​​​​https://blog.csdn.net/hnjzsyjyj/article/details/152234376

【算法代码】
本代码中的 dfs1 + getLCA 是倍增法求 LCA 的代码。详见:https://blog.csdn.net/hnjzsyjyj/article/details/152203103
之后,dfs2 通过后序遍历完成树形差分的合并,将差分标记转化为每条边的实际覆盖次数。也就是说,dfs2 解决 “次数怎么算”的问题。

#include <bits/stdc++.h>
using namespace std;const int N=5e5+5;
const int LOG=20;
int f[N][LOG+5],dep[N],d[N];
vector<int> g[N];
int n,m,ans;void dfs1(int u,int fa) { //preprocessdep[u]=dep[fa]+1;f[u][0]=fa;for(int i=1; (1<<i)<=dep[u]; i++) { //i<=LOGf[u][i]=f[f[u][i-1]][i-1];}for(auto j:g[u]) {if(j!=fa) dfs1(j,u);}
}int getLCA(int u,int v) {if(dep[u]<dep[v]) swap(u,v);for(int i=LOG; i>=0; i--) {if(dep[f[u][i]]>=dep[v]) u=f[u][i];}if(u==v) return u;for(int i=LOG; i>=0; i--) {if(f[u][i]!=f[v][i]) {u=f[u][i],v=f[v][i];}}return f[u][0];
}void dfs2(int u,int fa) {for(auto j:g[u]) {if(j!=fa) dfs2(j,u),d[u]+=d[j];}
}int main() {ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);cin>>n>>m;for(int i=1; i<n; i++) {int x,y;cin>>x>>y;g[x].push_back(y);g[y].push_back(x);}dfs1(1,-1);while(m--) {int x,y,lca;cin>>x>>y;lca=getLCA(x,y);d[x]++,d[y]++;d[lca]--,d[f[lca][0]]--;}dfs2(1,-1);for(int i=1; i<=n; i++) {ans=max(ans,d[i]);}cout<<ans<<endl;return 0;
}/*
in:
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 4out:
9
*/





【参考文献】
https://www.bilibili.com/video/BV1bg4y127QH
https://blog.csdn.net/hnjzsyjyj/article/details/157199762
https://blog.csdn.net/hnjzsyjyj/article/details/157245297​​​​​​​
https://www.cnblogs.com/Chase-s/p/10410265.html
https://www.cnblogs.com/hetailang/p/16216504.html
https://blog.51cto.com/u_13536312/5371363
https://www.acwing.com/solution/content/186355/
 

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询