[USACO15DEC]最大流Max Flow
原题链接 最大流Max Flow
题目大意
给你 \(n - 1\) 条边,再给你 \(m\) 个操作,每次操作两个数 \(u, v\) 表示,\(u, v\) 的最短路径上每个点都加上\(1\)
题目题解
树上差分的经典题 (一直想学树上差分,今天终于会了quq),我们修改时,使\(power_u\)++ ,\(power_v\)++,\(power_{lca(u,v)}\)--,\(power_{f[lca(u,v)][0]}\)-- 就可以了
接下来就是代码..xx
//#define fre yes #include <cstdio> #include <cstring> #include <iostream> int n, m; const int N = 50005; int head[N << 1], to[N << 1], ver[N << 1]; int f[N][22], lg[N], depth[N], power[N]; int tot; void addedge(int x, int y) { ver[tot] = y; to[tot] = head[x]; head[x] = tot++; } void dfs(int x, int fa) { depth[x] = depth[fa] + 1; f[x][0] = fa; for (int i = 1; (1 << i) <= depth[x]; i++) { f[x][i] = f[f[x][i - 1]][i - 1]; } for (int i = head[x]; ~i; i = to[i]) { int v = ver[i]; if(v != fa) { dfs(v, x); } } } int ans; void sum(int u, int fa) { for (int i = head[u]; ~i; i = to[i]) { int v = ver[i]; if(v != fa) { sum(v, u); power[u] += power[v]; } } ans = std::max(ans, power[u]); } int lca(int u, int v) { if(depth[u] < depth[v]) { std::swap(u, v); } while(depth[u] > depth[v]) { u = f[u][lg[depth[u] - depth[v]] - 1]; } if(u == v) return u; for (int i = lg[depth[u]] - 1; i >= 0; i--) { if(f[u][i] != f[v][i]) { u = f[u][i]; v = f[v][i]; } } return f[u][0]; } int main() { memset(head, -1, sizeof(head)); scanf("%d %d", &n, &m); for (int i = 1; i <= n - 1; i++) { int u, v; scanf("%d %d", &u, &v); addedge(u, v); addedge(v, u); } dfs(1, -1); for (int i = 1; i <= n; i++) { lg[i] = lg[i - 1] + (1 << lg[i - 1] == i); } for (int i = 1; i <= m; i++) { int x, y; scanf("%d %d", &x, &y); int lc = lca(x, y); ++power[x]; ++power[y]; --power[lc]; --power[f[lc][0]]; } sum(1, -1); printf("%d\n", ans); return 0; }
来源:https://www.cnblogs.com/Nicoppa/p/11485748.html