P3128 [USACO15DEC]最大流Max Flow-樹上點差分-第一彈
阿新 • • 發佈:2018-12-03
- P3128 [USACO15DEC]最大流Max Flow
- 樹上差分,顧名思義就是在樹上搞差分,點差分:
- 我們在power[lca(u,v)]-=x,而是把power[lca(u,v)]-=x並把power[dp[lca(u,v)]]-=x。
- 因為lca(u,v)也在u..v這條路徑上,它同樣需要被加x。回溯的時候會從u和v兩個方向都給lca(u,v)加一個x。
- 而它只能加一個,因此power[lca(u,v)]-=x。而lca(u,v)的爸爸則根本無法被加,在lca(u,v)已經只加一個x了.
- 因此power[dp[lca(u,v)]]-=x就能讓lca(u,v)的爸爸不加x。
-
#include<bits/stdc++.h> using namespace std; #define maxn 123456 int n,head[maxn],deep[maxn],power[maxn]; int cnt,ans,x,y,k,dp[maxn][50],lcaaaaa; struct edg { int v,to; } edge[maxn]; void adda(int x,int y) { edge[++cnt].to=head[x]; edge[cnt].v=y; head[x]=cnt; } void dfs(int cur,int fa) { deep[cur]=deep[fa]+1; dp[cur][0]=fa; for(int i=1; (1<<i)<=deep[cur]; i++) dp[cur][i]=dp[dp[cur][i-1]][i-1]; for(int i=head[cur]; i!=-1; i=edge[i].to) if(edge[i].v!=fa) dfs(edge[i].v,cur); } int lca(int x,int y) { if(deep[x]<deep[y]) swap(x,y); for(int i=30; i>=0; i--) if(deep[x]-(1<<i)>=deep[y]) x=dp[x][i]; if(x==y)return x; for(int i=30; i>=0; i--) if(dp[x][i]!=dp[y][i]) { x=dp[x][i]; y=dp[y][i]; } return dp[x][0]; } void get(int cur,int fa) { for(int i=head[cur]; i!=-1; i=edge[i].to) { if(edge[i].v==fa)continue; get(edge[i].v,cur); power[cur]+=power[edge[i].v]; } ans=max(ans,power[cur]); } int main() { memset(head,-1,sizeof(head)); scanf("%d%d",&n,&k); for(int i=1; i<n; i++) { scanf("%d%d",&x,&y); adda(x,y); adda(y,x); } deep[0]=0; dfs(1,0); while(k--) { scanf("%d%d",&x,&y); lcaaaaa=lca(x,y); power[x]++; power[y]++; power[lcaaaaa]--; power[dp[lcaaaaa][0]]--; } get(1,0); printf("%d\n",ans); return 0; }