P4103 [HEOI2014] Big Project
Title Description
See: P4103 [HEOI2014] Big Project
Solution
Obviously, it's the boarding question of the virtual tree (I didn't make why I adjusted it for an hour)
Direct virtual tree, DP.
Two or two paths and good demand, as long as the contribution of each side is considered, set upFor the number of key points to ask,
For subtrees
Number of key points.
For maximum and minimum paths,
Set upIn order to
The middle distance of the root subtree
Distance from the farthest point,
In order to
The middle distance of the root subtree
Distance from the nearest point.
Then there's no more.
Code
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int MAXN=3e6+50; const int INF=0x3f3f3f3f; bool Flag[MAXN]; ll ans1; int dis[MAXN],ans2,ans3,k,DFN=0,Log[MAXN],a[MAXN]; int stk[MAXN],mn[MAXN],mx[MAXN],size[MAXN],fa[MAXN][21],dep[MAXN],dfn[MAXN],top; vector<int> e[MAXN],son[MAXN]; inline int read() { int x=0,f=1; char c=getchar(); while (c<'0'||c>'9') { if(c=='-') f=-1; c=getchar(); } while (c>='0'&&c<='9') { x=(x<<3)+(x<<1)+(c^48); c=getchar(); } return x*f; } void add_edge(int u,int v){ son[u].push_back(v); } void tree_dp(int x,int father) { //cout<<x<<" "<<father<<endl; for (int i=0;i<son[x].size();i++) if (son[x][i]!=father) tree_dp(son[x][i],x); mx[x]=Flag[x]?0:-INF,mn[x]=Flag[x]?0:INF,size[x]=Flag[x]; for (int i=0;i<son[x].size();i++) if (son[x][i]!=father) { int len=(dep[son[x][i]]-dep[x]); ans1+=1ll*size[son[x][i]]*(k-size[son[x][i]])*len; if (size[x]>0) { ans2=max(ans2,mx[x]+mx[son[x][i]]+len); ans3=min(ans3,mn[x]+mn[son[x][i]]+len); } mx[x]=max(mx[x],mx[son[x][i]]+len); mn[x]=min(mn[x],mn[son[x][i]]+len); size[x]+=size[son[x][i]]; } Flag[x]=0; son[x].clear(); } int get_lca(int x,int y) { if (dep[x]<dep[y]) swap(x,y); for (int i=Log[dep[x]];i>=0;i--) if (dep[fa[x][i]]>=dep[y]) x=fa[x][i]; if (x==y) return x; for (int i=Log[dep[x]];i>=0;i--) if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; return fa[x][0]; } void insert(int x) { if (top==1) { stk[++top]=x; return; } int lca=get_lca(stk[top],x); if (lca==stk[top]) { stk[++top]=x; return; } while (top>1&&dfn[stk[top-1]]>=dfn[lca]) add_edge(stk[top-1],stk[top]),top--; if (stk[top]!=lca) add_edge(lca,stk[top]),stk[top]=lca; stk[++top]=x; } void dfs(int x,int father) { dep[x]=dep[father]+1; fa[x][0]=father; dfn[x]=++DFN; for (int i=1;i<=Log[dep[x]];i++) fa[x][i]=fa[fa[x][i-1]][i-1]; for (int i=0;i<e[x].size();i++) if (e[x][i]!=father) dfs(e[x][i],x); } int compare(int x,int y){return dfn[x]<dfn[y]; } int main() { int n=read(); for (int i=1;i<n;i++) { int u=read(),v=read(); e[u].push_back(v); e[v].push_back(u); } dep[0]=-1,Log[1]=0; for (int i=2;i<=n;i++) Log[i]=Log[i>>1]+1; dfs(1,0); int Case=read(); while (Case--) { ans1=0,ans2=0,ans3=INF; k=read(); for (int i=1;i<=k;i++) a[i]=read(); sort(a+1,a+k+1,compare); stk[top=1]=1,size[1]=1; for (int i=1;i<=k;i++) { Flag[a[i]]=1; if (a[i]!=1) insert(a[i]),size[a[i]]=1; } while (top>1) add_edge(stk[top-1],stk[top]),top--; tree_dp(1,0); printf("%lld %d %d\n",ans1,ans3,ans2); } return 0; }
Code indentation has been done again...