[USACO15DEC]最大流Max Flow

树剖LCA+树上差分。
树上差分的基本操作。

#include <queue>
#include <iostream>
#include <cstdio>
using namespace std;
const int N=100005;
int head[N],ecnt,dfn[N],top[N],son[N],fa[N],tim,dep[N],siz[N],rnk[N],nums[N],sum[N];
struct Edge{int to,nxt;}e[N<<1];
void add(int bg,int ed) {e[++ecnt].nxt=head[bg];e[ecnt].to=ed;head[bg]=ecnt;}
void dfs1(int x) {
	siz[x]=1;
	for(int i=head[x];i;i=e[i].nxt) {
		int v=e[i].to;
		if(v!=fa[x]){nums[x]++;fa[v]=x;dep[v]=dep[x]+1;dfs1(v);siz[x]+=siz[v];son[x]=siz[v]>siz[son[x]]?v:son[x];}
	}
}
void dfs2(int x,int qtop) {
	top[x]=qtop;dfn[x]=++tim;rnk[tim]=x;
	if(son[x]) dfs2(son[x],qtop);
	for(int i=head[x];i;i=e[i].nxt){
		int v=e[i].to;
		if(v!=fa[x]&&v!=son[x]) {dfs2(v,v);}
	}
}
int lca(int x,int y) {
	while(top[x]!=top[y]) {
			(dep[top[x]]>=dep[top[y]])?x=fa[top[x]]:y=fa[top[y]];
	}
	return dep[x]>dep[y]?y:x;
}
int n,K;
int main() {
	scanf("%d%d",&n,&K);
	for(int i=1,x,y;i<n;i++) {scanf("%d%d",&x,&y);add(x,y);add(y,x);}
	dfs1(1);dfs2(1,1);
	for(int i=1,x,y;i<=K;i++) {
		scanf("%d%d",&x,&y);
		int LCA=lca(x,y);
		sum[x]++,sum[y]++,sum[LCA]--,sum[fa[LCA]]--;
	}
	queue<int>q;
	for(int i=1;i<=n;i++) if(siz[i]==1) q.push(i);
	int ans=0;
	while(!q.empty()) {
		int u=q.front();q.pop();
		int v=fa[u];
		nums[v]--;
		sum[v]+=sum[u];
		ans=max(ans,sum[v]);
		if(!nums[v]) q.push(v);
	}
	printf("%d",ans);
}
posted @ 2018-07-28 09:01  SWHsz  阅读(146)  评论(0编辑  收藏  举报