P3128 [USACO15DEC]最大流Max Flow

题面:https://www.luogu.org/problem/P3128

树上差分裸题,那么在这里再讲一下树上差分:
一、点差分
val[u]++,val[v]++,val[lca(u,v)]--,val[fa[lca(u,v)]]--;
这里是因为要有一条链上包含lca
二、边差分
val[u]++,val[v]++,val[lca(u,v)]-=2;
这里由于lca连向fa[lca]的边也不用计入答案,所以val[lca(u,v)]-=2
Code:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<ctime>
#include<set>
using namespace std;
const int N=50005;
int n,k,head[N],cnt,anc[N][25],fa[N],dep[N];
long long val[N],ans;
long long max(long long p,long long q){
	return p>q?p:q;
}
struct Node{
	int u,v,nxt;
}edge[N*2];
void add(int u,int v){
	++cnt;
	edge[cnt].u=u;
	edge[cnt].v=v;
	edge[cnt].nxt=head[u];
	head[u]=cnt;
}
void dfs(int u){
	anc[u][0]=fa[u];
	for(int i=1;i<=22;i++){
		anc[u][i]=anc[anc[u][i-1]][i-1];
	}
	for(int i=head[u];i;i=edge[i].nxt){
		int v=edge[i].v;
		if(v!=fa[u]){
			fa[v]=u;
			dep[v]=dep[u]+1;
			dfs(v);
		}
	}
}
int lca(int x,int y){
	if(dep[x]<dep[y]){
		swap(x,y);
	}
	for(int i=22;i>=0;i--){
		if(dep[anc[x][i]]>=dep[y]){
			x=anc[x][i];
		}
	}
	if(x==y){
		return x;
	}
	for(int i=22;i>=0;i--){
		if(anc[x][i]!=anc[y][i]){
			x=anc[x][i];
			y=anc[y][i];
		}
	}
	return anc[x][0];
}
void calc(int u){
	for(int i=head[u];i;i=edge[i].nxt){
		int v=edge[i].v;
		if(v!=fa[u]){
			calc(v);
			val[u]+=val[v];
		}
	}
}
int main(){
	int u,v;
	scanf("%d%d",&n,&k);
	for(int i=1;i<n;i++){
		scanf("%d%d",&u,&v);
		add(u,v);
		add(v,u);
	}
	dep[1]=1;
	dfs(1);
	for(int i=1;i<=k;i++){
		scanf("%d%d",&u,&v);
		int it=lca(u,v);
		val[u]++;
		val[v]++;
		val[it]--;
		val[fa[it]]--;
	}
	calc(1);
	for(int i=1;i<=n;i++){
		ans=max(ans,val[i]);
	}
	printf("%lld\n",ans);
	return 0;
}
posted @ 2019-10-14 20:13  prestige  阅读(101)  评论(0编辑  收藏  举报