1. 程式人生 > >luoguP3128 [USACO15DEC]最大流Max Flow 題解(樹上差分)

luoguP3128 [USACO15DEC]最大流Max Flow 題解(樹上差分)

gist ref dep efi != ace head turn gis

鏈接一下題目:luoguP3128 [USACO15DEC]最大流Max Flow(樹上差分板子題)

如果沒有學過樹上差分,摳這裏(其實很簡單的,真的):樹上差分總結

學了樹上差分,這道題就極其顯然了,不就是把每一條運輸路線差分進去,那就是板子了啊.

樹上差分還是很有用的,比較容易寫,這種詢問很少的題目去敲那麽長(還容易出玄學錯誤)的樹剖很浪費,用樹上差分就很快了!(//...微笑...\\)

上一波代碼:

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include
<cstring> #include<algorithm> #include<iomanip> #include<ctime> #include<queue> #include<stack> #define rg register #define lst long long #define N 50050 using namespace std; int n,K,cnt,ans; struct EDGE{ int to,nxt; }edge[N<<1]; int head[N]; int fa[N],v[N],deep[N];
int f[N][25]; inline int read() { rg int s=0,m=1;rg char ch=getchar(); while(ch!=-&&(ch<0||ch>9))ch=getchar(); if(ch==-)m=-1,ch=getchar(); while(ch>=0&&ch<=9)s=(s<<3)+(s<<1)+ch-0,ch=getchar(); return s*m; } inline void add(rg int
p,rg int q) { edge[++cnt]=(EDGE){q,head[p]}; head[p]=cnt; } void dfs(rg int now,rg int fm,rg int dep)//點,父親,深度 { fa[now]=fm;deep[now]=dep; f[now][0]=fa[now]; for(rg int i=1;i<=20;++i) f[now][i]=f[f[now][i-1]][i-1]; for(rg int i=head[now];i;i=edge[i].nxt) { rg int qw=edge[i].to; if(qw!=fm) dfs(qw,now,dep+1); } } inline int lca(rg int p,rg int q) { if(deep[p]<deep[q])swap(p,q); while(deep[p]>deep[q]) for(rg int i=20;i>=0;--i) if(deep[f[p][i]]>=deep[q]) p=f[p][i]; while(p!=q) { for(rg int i=20;i>=0;--i) if(f[p][i]!=f[q][i]) p=f[p][i],q=f[q][i]; if(fa[p]==fa[q]) p=q=fa[p]; } if(p==q)return p; } inline void Insert(rg int p,rg int q)//如模板,差分 { v[p]++,v[q]++;//自己++ rg int LCA=lca(p,q); // printf("lca(%d,%d)=%d\n",p,q,LCA); v[LCA]--,v[fa[LCA]]--;//LCA和fa[LCA]-- } void sum(rg int now) { for(rg int i=head[now];i;i=edge[i].nxt) { rg int qw=edge[i].to; if(qw!=fa[now]) { sum(qw); v[now]+=v[qw]; } } ans=max(ans,v[now]); } int main() { n=read(),K=read(); for(rg int i=1;i<n;++i) { rg int p=read(),q=read(); add(p,q),add(q,p); } dfs(1,0,1);//倍增的預處理 // for(rg int i=\1;i<=n;++i)cout<<deep[i]<<" ";cout<<endl; /* for(rg int i=1;i<=n;++i) { for(rg int j=0;j<=2;j++) { printf("f[%d][%d]=%d ",i,j,f[i][j]); } cout<<endl; } cout<<endl;*/ for(rg int i=1;i<=K;++i) { rg int p=read(),q=read(); Insert(p,q);//差分 } add(0,1);//0上面也會有標記,所以上面的東西也要弄掉 sum(0);//dfs遍歷順便找答案 printf("%d\n",ans); return 0; }

luoguP3128 [USACO15DEC]最大流Max Flow 題解(樹上差分)