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;
}