BZOJ 3611 [Heoi2014]大工程 ——虚树
虚树第二题。。。。
同BZOJ2286
#include <map> #include <cmath> #include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define F(i,j,k) for (int i=j;i<=k;++i) #define D(i,j,k) for (int i=j;i>=k;--i) #define ll long long #define mp make_pair #define inf 0x3f3f3f3f #define maxn 2000005 int h[maxn],to[maxn],ne[maxn],en=0; int n,dep[maxn],st[maxn][22],in[maxn],out[maxn],ord[maxn],tot; int _log[maxn],m,sta[maxn],top=0,se[maxn],idx,k,a[maxn]; void add(int a,int b) {to[en]=b;ne[en]=h[a];h[a]=en++;} void dfs1(int o,int fa) { in[o]=++tot;ord[tot]=o; for (int i=h[o];i>=0;i=ne[i]) if (to[i]!=fa) { dep[to[i]]=dep[o]+1; dfs1(to[i],o); ord[++tot]=o; } out[o]=tot; } void initst() { F(i,2,maxn-1) _log[i]=_log[i>>1]+1; F(i,1,21) F(j,1,tot-(1<<i)+1) { if (dep[st[j][i-1]]<dep[st[j+(1<<i-1)][i-1]]) st[j][i]=st[j][i-1]; else st[j][i]=st[j+(1<<i-1)][i-1]; } } int lca(int l,int r) { l=in[l];r=in[r];if (l==r) return st[l][0]; if (l>r) swap(l,r);int tmp=_log[r-l+1]; if (dep[st[l][tmp]]<dep[st[r-(1<<tmp)+1][tmp]]) return st[l][tmp]; else return st[r-(1<<tmp)+1][tmp]; } void debug() { int a,b; while (scanf("%d%d",&a,&b)!=EOF) printf("%d\n",lca(a,b)); } bool cmp(int a,int b) { return in[a]<in[b]; } int hd[maxn],tl[maxn],nxt[maxn],ed,lst[maxn]; void add_edge(int a,int b) { if (lst[a]!=idx) lst[a]=idx,hd[a]=-1; tl[ed]=b; nxt[ed]=hd[a]; hd[a]=ed++; } int siz[maxn],mn[maxn],mx[maxn],ans_max,ans_min; ll dfs2(int o,int fa) { siz[o]=0;ll ret=0; mn[o]=inf;mx[o]=-inf; if (se[o]==idx) mn[o]=0,mx[o]=0,siz[o]++; for (int i=hd[o];i>=0;i=nxt[i]) if (tl[i]!=fa){ ret+=dfs2(tl[i],o); siz[o]+=siz[tl[i]]; ans_max=max(ans_max,mx[o]+mx[tl[i]]+dep[tl[i]]-dep[o]); ans_min=min(ans_min,mn[o]+mn[tl[i]]+dep[tl[i]]-dep[o]); mn[o]=min(mn[o],mn[tl[i]]+dep[tl[i]]-dep[o]); mx[o]=max(mx[o],mx[tl[i]]+dep[tl[i]]-dep[o]); } for (int i=hd[o];i>=0;i=nxt[i]) if (tl[i]!=fa){ ret+=((ll)k-(ll)siz[tl[i]])*(ll)siz[tl[i]]*((ll)dep[tl[i]]-(ll)dep[o]); } return ret; } int main() { memset(h,-1,sizeof h); scanf("%d",&n); F(i,2,n) { int a,b;scanf("%d%d",&a,&b); add(a,b);add(b,a); } dfs1(1,-1); F(i,1,tot) st[i][0]=ord[i]; initst(); scanf("%d",&m); for (idx=1;idx<=m;++idx) { ed=0; scanf("%d",&k); F(i,1,k) scanf("%d",&a[i]); sort(a+1,a+k+1,cmp); int rt=a[1];F(i,2,k) rt=lca(rt,a[i]); sta[top=1]=rt; F(i,1,k) { se[a[i]]=idx; if (a[i]==rt) continue; int x=lca(a[i],sta[top]); //printf("Add and lca is %d\n",x); while(dep[x]<dep[sta[top]]) { int tmp; if (dep[x]>dep[sta[top-1]])tmp=x; else tmp=sta[top-1]; add_edge(sta[top],tmp); add_edge(tmp,sta[top]); top--; } if (x!=sta[top]) sta[++top]=x; sta[++top]=a[i]; } while (top>1) add_edge(sta[top],sta[top-1]),add_edge(sta[top-1],sta[top]),top--; ans_max=-inf;ans_min=inf; printf("%lld",dfs2(rt,0)); printf(" %d %d\n",ans_min,ans_max); } }