USACO 2015 December Contest Max Flow (bzoj4390)
给定一棵有N个点的树,所有节点的权值都为0。
有K次操作,每次指定两个点s,t,将s到t路径上所有点的权值都加一。
请输出K次操作完毕后权值最大的那个点的权值。
很裸的一道题,树剖+查分 将val[x]+1,val[y]+1,val[lca]-1,val[fa[lca]]-1
最后统计就好了。
#include <stdio.h> #include <algorithm> #include <cstring> #include <cmath> #include <queue> #include <vector> using namespace std; const int maxn=50000+10; const int maxm=500000+10; int n,k,point,ans; int size[maxn],fa[maxn],head[maxn],dep[maxn],bel[maxn],val[maxn]; struct hh { int v,next; }e[maxm*2]; template <class T> void read(T&x) { x=0;char c=getchar();int f=0; while(c<'0'||c>'9'){f|=(c=='-');c=getchar();} while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar(); x=f?-x:x; } void add(int u,int v) { e[++point].v=v;e[point].next=head[u];head[u]=point; e[++point].v=u;e[point].next=head[v];head[v]=point; } void dfs(int x) { size[x]=1; for(int i=head[x];~i;i=e[i].next) { if(e[i].v==fa[x])continue; fa[e[i].v]=x; dep[e[i].v]=dep[x]+1; dfs(e[i].v); size[x]+=size[e[i].v]; } return; } void dfs1(int x,int chain) { int k=0;bel[x]=chain; for(int i=head[x];~i;i=e[i].next) if(dep[e[i].v]>dep[x]&&size[e[i].v]>size[k])k=e[i].v; if(!k)return; dfs1(k,chain); for(int i=head[x];~i;i=e[i].next) if(dep[e[i].v]>dep[x]&&e[i].v!=k) dfs1(e[i].v,e[i].v); } void dfs2(int x) { for(int i=head[x];~i;i=e[i].next) if(dep[e[i].v]>dep[x]) { dfs2(e[i].v); val[x]+=val[e[i].v]; } if(ans<val[x])ans=val[x]; return; } int lca(int x,int y) { while(bel[x]!=bel[y]) { if(dep[bel[x]]<dep[bel[y]]){x^=y;y^=x;x^=y;} x=fa[bel[x]]; } return dep[x]<=dep[y]?x:y; } int main() { memset(head,-1,sizeof(head)); dep[1]=1; read(n);read(k); for(int i=1;i<n;i++) { int u,v;read(u);read(v); add(u,v); } dfs(1); dfs1(1,1); for(int i=1;i<=k;i++) { int x,y;read(x);read(y); int lf=lca(x,y); val[x]++;val[y]++; val[lf]--;val[fa[lf]]--; } dfs2(1); printf("%d",ans); return 0; }