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;
}
posted @ 2025-12-16 21:38  To_Carpe_Diem  阅读(3)  评论(0)    收藏  举报