题解 P3128 【[USACO15DEC]最大流Max Flow】

题目描述

FJ给他的牛棚的N(2≤N≤50,000)个隔间之间安装了N-1根管道,隔间编号从1到N。所有隔间都被管道连通了。

FJ有K(1≤K≤100,000)条运输牛奶的路线,第i条路线从隔间si运输到隔间ti。一条运输路线会给它的两个端点处的隔间以及中间途径的所有隔间带来一个单位的运输压力,你需要计算压力最大的隔间的压力是多少。

主要思路 : LCA + 树上差分

如果您还不会差分,那就去这个神奇的网站去找一找差分吧(逃

这是道树上差分裸题。

论如何树上做差分,,,

还记得序列上差分是怎么做的吗(QAQ)

假如我们要把一段区间的数据+1,我们根据差的性质把左端点维护差分的数组相应位置+1,右端点-1。

树上差分也类似。我们只需要把两个端点-1,两个端点的lca -2,(为啥-2,emmm,因为有两个端点要+1啊)。

但是这样就会发现lca处求出的并没有+1,我们可以使得lca处-1就好,保证之后的点加的时候会有+1的效果,我们在lca的父节点处也-1,保证lca处是有+1效果的。

所以就这么搞啦!

code :

P.S. : (树剖LCA打习惯了QAQ

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <cmath>
#include <algorithm>
#include <queue>
#include <map>
#include <vector>
using namespace std;
#define go(i, j, n, k) for(int i = j; i <= n; i += k)
#define fo(i, j, n, k) for(int i = j; i >= n; i -= k)
#define rep(i, x) for(int i = h[x]; i; i = e[i].nxt)
#define mn 100010
#define inf 1 << 30
#define ll long long
inline int read() {
	int x=0,f=1;char ch=getchar();
	while(ch>'9'||ch<'0'){if(ch=='-')f=-f;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x * f;
}
struct edge{
	int v, nxt;
}e[mn << 1];
int h[mn], p;
inline void add(int a, int b) {
	e[++p].nxt = h[a], h[a] = p, e[p].v = b;
}
int dep[mn], sze[mn], fa[mn], son[mn], top[mn], cnt, n, m, _minus[mn], ans = -1;
void dfs1(int x, int f, int deep) {
	dep[x] = deep;
	sze[x] = 1;
	fa[x] = f;
	int maxson = -1;
	rep(i, x) {
		int v = e[i].v;
		if(v == f) continue;
		dfs1(v, x, deep + 1);
		sze[x] += sze[v];
		if(sze[v] > maxson)
			maxson = sze[v], son[x] = v;
	}
}
void dfs2(int x, int topf) {
	top[x] = topf;
	if(!son[x]) return;
	dfs2(son[x], topf);
	rep(i, x) {
		int v = e[i].v;
		if(v == fa[x] || v == son[x]) continue;
		dfs2(v, v);
	}
}
inline int LCA(int x, int y) {
	while(top[x] != top[y]) {
		if(dep[top[x]] < dep[top[y]]) swap(x, y);
		x = fa[top[x]];
	}
	return dep[x] > dep[y] ? y : x;
}
inline void dfs(int x, int f) {
	rep(i, x) {
		int v = e[i].v;
		if(v == f) continue;
		dfs(v, x);
		_minus[x] += _minus[v];
	}
	ans = max(ans, _minus[x]);
}
int main() {
	n = read(), m = read();
	go(i, 1, n - 1, 1) {
		int a = read(), b = read();
		add(a, b), add(b, a);
	}
	dfs1(1, 0, 1); // 树剖预处理的哦QAQ
	dfs2(1, 1);    // 树剖预处理的哦QAQ
	go(i, 1, m, 1) {
		int a = read(), b = read(), lca = LCA(a, b);
		_minus[a]++, _minus[b]++, _minus[lca]--, _minus[fa[lca]]--; 
        // 不要问我的数组变量名之前加‘_’,你可以试一下不加 
	}
	dfs(1, 0);     // 差分完了就做个树上前缀和就好辣!~(≧▽≦)/~
	cout << ans << "
";
	return 0;
}
原文地址:https://www.cnblogs.com/yizimi/p/10056313.html