P3128 [USACO15DEC] Max Flow P
P3128 [USACO15DEC] Max Flow P
大意
每次将树上的一条路径的点权值加 \(1\),给你 \(u, v\),最后让你求树上最大的点权是什么。
思路
考虑树上差分。
模板题了几乎是。
我们定义差分数组 \(d\),然后我们直接在 \(d_u, d_v\) 加 \(1\),在 \(d_{lca(u, v)}\) 减 \(1\),在 \(d_{fa_{lca(u, v)}}\) 减 \(1\),最后作一个类似前缀和的东西,直接算就好。
代码
#include<iostream>
#include<vector>
using namespace std;
const int MAXN = 5 * 1e4 + 5;
const int LOG = 20;
int d[MAXN], dep[MAXN];
int f[MAXN][LOG];
int n, K;
vector<int> e[MAXN];
void dfs1(int u, int fa){
dep[u] = dep[fa] + 1;
f[u][0] = fa;
for(int i = 0;i < e[u].size();i ++){
int v = e[u][i];
if(v == fa) continue;
dfs1(v, u);
}
}
void I_nt(){
for(int k = 1;k < LOG;k ++){
for(int i = 1;i <= n;i ++){
f[i][k] = f[f[i][k - 1]][k - 1];
}
}
}
int LCA(int u, int v){
if(dep[u] < dep[v]) swap(u, v);
for(int k = LOG - 1;k >= 0;k --){
if(dep[f[u][k]] >= dep[v]){
u = f[u][k];
}
}
if(u == v) return u;
for(int k = LOG - 1;k >= 0;k --){
if(f[u][k] != f[v][k]){
u = f[u][k], v = f[v][k];
}
}
return f[u][0];
}
int ans = 0;
void dfs2(int u, int fa){
for(int i = 0;i < e[u].size();i ++){
int v = e[u][i];
if(v == fa) continue;
dfs2(v, u);
d[u] += d[v];
}
ans = max(ans, d[u]);
}
int main(){
cin >> n >> K;
for(int i = 1;i < n;i ++){
int u, v; cin >> u >> v;
e[u].push_back(v);
e[v].push_back(u);
}
dfs1(1, 0);
I_nt();
for(int i = 1;i <= K;i ++){
int u, v; cin >> u >> v;
d[u] ++;
d[v] ++;
d[LCA(u, v)] --;
d[f[LCA(u, v)][0]] --;
}
dfs2(1, 0);
cout << ans << '\n';
return 0;
}
本文来自一名高中生,作者:To_Carpe_Diem

浙公网安备 33010602011771号