LCA-> Max Flow P(洛谷3128)
题意:n个节点m个询问,每次询问2个输入,u和v两个节点,代表u,v之间的路径权值+1。求m次询问后权值最大的节点。
分析:明显树上差分,将u,v作为区间起点,祖先作为和祖先的父亲作为差分区间结尾。
思考:为什么要从下往上差分,从上往下差分为什么不行呢
求LCA的时候算法写错了,往上跳的时候没跳u,把depth[u]跳了..
void solve(){
int n, m;
cin >> n >> m;
vector<vector<int>> al(n + 1);
for (int i = 1; i < n; ++i){
int u, v;
cin >> u >> v;
al[u].emplace_back(v);
al[v].emplace_back(u);
}
int p = upper_bound(pow2_values.begin(), pow2_values.end(), n) - pow2_values.begin() - 1;
vector<int> depth(n + 1);
vector<vector<int>> dp(n + 1, vector<int>(p + 1));
function<void(int, int, int)> dfs = [&](int u, int p, int d){
depth[u] = d;
dp[u][0] = p;
for (int i = 1; (1 << i) <= d; ++i){
dp[u][i] = dp[dp[u][i - 1]][i - 1];
}
for (const auto& v : al[u]){
if (v != p){
dfs(v, u, d + 1);
}
}
};
function<int(int, int)> lca = [&](int u, int v){
if (depth[u] < depth[v]){
swap(u, v);
}
for (int i = p; i >= 0; --i){
if (depth[u] - (1 << i) >= depth[v]){
u = dp[u][i];
}
}
if (u == v){
return u;
}
for (int i = p; i >= 0; --i){
if (dp[u][i] != dp[v][i]){
u = dp[u][i];
v = dp[v][i];
}
}
return (dp[u][0]);
};
dfs(1, 0, 1);
vector<int> weight(n + 1);
while (m --){
int u, v;
cin >> u >> v;
int anc = lca(u, v);
auto deal = [&](int ancestor){
weight[ancestor] ++;
for (auto& t : al[u]){
if (t != dp[u][0]){
weight[t] --;
}
}
for (auto& t : al[v]){
if (t != dp[v][0]){
weight[t] --;
}
}
};
deal(anc);
}
int ans = 0;
function<void(int, int, int w)> dfs_ = [&](int u, int p, int w){
ans = max(ans, w);
for (auto& v : al[u]){
if (v != p){
dfs_(v, u, w + weight[v]);
}
}
};
dfs_(1, 0, weight[1]);
cout << ans << '\n';
}

浙公网安备 33010602011771号