P3128 [USACO15DEC] Max Flow P 题解
简化题意:
给出一棵
分析:
树上差分板子。
先回顾一下序列差分:
序列差分经典题就是进行若干次修改,最终求出整个序列。
因为差分是前缀和的逆操作,所以对差分数组进行前缀和就可以还原原数组。
假设我们要对
树上差分类似,一般是对树上的若干链进行修改操作,最终求整棵树的所有点权。
我们首先对这棵树确定一个根(一般为
所以,如果我们要修改路径
求 LCA 的方法很多,具体参考本文,下方代码使用了树剖求法。
#include<bits/stdc++.h>
using namespace std;
const int N = 5e4 + 9;
struct edge{
int to,nex;
} e[N << 1];
int ecnt,head[N];
int top[N],dep[N];
int fa[N],weight_child[N],siz[N];
void addedge(int u,int v){
ecnt++;
e[ecnt] = (edge){v,head[u]};
head[u] = ecnt;
}
int val[N];
int n,k,ans;
void dfs1(int cur,int father){
fa[cur] = father;
siz[cur] = 1;
dep[cur] = dep[father] + 1;
for(int i = head[cur];i;i = e[i].nex){
int v = e[i].to;
if(v != father){
dfs1(v,cur);
siz[cur] += siz[v];
if(siz[v] > siz[weight_child[cur]])
weight_child[cur] = v;
}
}
}
void dfs2(int cur,int link_top){
top[cur] = link_top;
if(weight_child[cur]){
dfs2(weight_child[cur],link_top);
for(int i = head[cur];i;i = e[i].nex){
int v = e[i].to;
if(v != fa[cur] && v != weight_child[cur])
dfs2(v,v);
}
}
}
int LCA(int u,int v){
while(top[u] != top[v]){
if(dep[top[u]] < dep[top[v]])
swap(u,v);
u = fa[top[u]];
}
return (dep[u] < dep[v]) ? u : v;
}
void dfs3(int cur){
for(int i = head[cur];i;i = e[i].nex){
int v = e[i].to;
if(v != fa[cur]){
dfs3(v);
val[cur] += val[v];
}
}
ans = max(ans,val[cur]);
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin >> n >> k;
for(int i = 1;i <= n - 1;i++){
int x,y;
cin >> x >> y;
addedge(x,y);
addedge(y,x);
}
dep[1] = 1;
dfs1(1,-1);
dfs2(1,-1);
for(int i = 1;i <= k;i++){
int x,y;
cin >> x >> y;
val[x]++;val[y]++;
int lca = LCA(x,y);
val[lca]--;val[fa[lca]]--;
}
dfs3(1);
cout << ans;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具