【学术篇】树上差分--洛谷3128最大流Max Flow
懒得贴题目,直接放不稳定的传送门(雾):点击前往暴风城(雾)
据说这题是BZOJ3490,但本蒟蒻没有权限╮(╯_╰)╭
这题似乎就是裸树上差分。。。
对于树上(x,y)之间的路径上的点区间c[i]加k<==>c[x]+=k,c[y]+=k,c[lca(x,y)]-=k,c[father[lca(x,y)]-=k
就是这样,虽然这题我因为各种智障的原因在luogu上交了3遍,为拉低这题通过率做出了巨大的贡献。。。
最后统计的时候从树根dfs一遍,把子节点的c值加到父节点上就行了~~
所以这题重点就是求lca(x,y)了,在这里我用了Tarjan,因为比倍增快,而且链剖LCA我也不会(或许也没有Tarjan快)。。
贴代码:
#include<cstdio> #define N 50005 #define M 100005 #define gc getchar struct edge { int to,next; }e[N<<1]; struct ques { int to,next,id; }f[M<<1]; int n,m,u[N],v[N],c[N],fa[N],up[N],ans[M],tot,tit=0,maxn=0; bool vis[N],vis2[N]; int find(int x) { return fa[x]==x?x:fa[x]=find(fa[x]); } void qin(int &a) { a=0;char c=gc();bool f=0; for(;(c<'0'||c>'9')&&c!='-';c=gc()); if(c=='-') f=1,c=gc(); for(;c>='0'&&c<='9';c=gc()) a=a*10+c-'0'; if(f) a=-a; } void build(int x,int y) { e[++tot].to=y; e[tot].next=v[x]; v[x]=tot; e[++tot].to=x; e[tot].next=v[y]; v[y]=tot; } void quest(int x,int y,int z) { f[++tit].to=y; f[tit].next=u[x]; u[x]=tit; f[tit].id=z; f[++tit].to=x; f[tit].next=u[y]; u[y]=tit; f[tit].id=z; } void dfs(int x) { vis[x]=1; fa[x]=x; for(int i=v[x];i;i=e[i].next) if(!vis[e[i].to]) up[e[i].to]=x,dfs(e[i].to),fa[e[i].to]=x; for(int i=u[x];i;i=f[i].next) if(vis[f[i].to]) ans[f[i].id]=find(f[i].to); } void dfs2(int x) { vis2[x]=1; for(int i=v[x];i;i=e[i].next) { int y=e[i].to; if(!vis2[y]) dfs2(y),c[x]+=c[y]; } if(c[x]>maxn) maxn=c[x]; } int main() { qin(n);qin(m); for(int i=1;i<n;i++) { int a,b;qin(a),qin(b); build(a,b); } for(int i=1;i<=m;i++) { int a,b;qin(a),qin(b); c[a]++;c[b]++; quest(a,b,i); } dfs(1); for(int i=1;i<=m;i++) c[ans[i]]--,c[up[ans[i]]]--; dfs2(1); printf("%d\n",maxn); }
嗯 就是这样。。。