bzoj3572[Hnoi2014]世界树
http://www.lydsy.com/JudgeOnline/problem.php?id=3572
首先我们先构建出虚树
然后在虚树上DP,求出虚树上每个点离最近的临时议事处在哪里
对于虚树上相邻的两个点$u$和$v$,他们连线上一定存在一个分界处,一边一定会去离$u$最近的临时议事处;另一边一定会去离$v$最近的临时议事处
然后就做完了
#include<cstdio> #include<cstdlib> #include<iostream> #include<fstream> #include<algorithm> #include<cstring> #include<string> #include<cmath> #include<queue> #include<stack> #include<map> #include<utility> #include<set> #include<bitset> #include<vector> #include<functional> #include<deque> #include<cctype> #include<climits> #include<complex> #include<cassert> //#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj using namespace std; typedef long long LL; typedef double DB; typedef pair<int,int> PII; typedef pair<DB,DB> PDD; typedef complex<DB> CP; typedef vector<int> VI; #define mmst(a,v) memset(a,v,sizeof(a)) #define mmcy(a,b) memcpy(a,b,sizeof(a)) #define fill(a,l,r,v) fill(a+l,a+r+1,v) #define re(i,a,b) for(i=(a);i<=(b);i++) #define red(i,a,b) for(i=(a);i>=(b);i--) #define fi first #define se second #define mp(a,b) make_pair(a,b) #define pb(a) push_back(a) #define SF scanf #define PF printf #define two(k) (1<<(k)) #define SZ(x) (int(x.size())) #define all(x) (x).begin(),(x).end() #define ire(i,v,x) for(i=0,v=i<SZ(x)?x[i]:0;i<SZ(x);v=x[++i]) template<class T>inline T sqr(T x){return x*x;} template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;} template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;} inline int sgn(DB x){if(abs(x)<1e-9)return 0;return(x>0)?1:-1;} const DB Pi=acos(-1.0); int gint() { int res=0;bool neg=0;char z; for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar()); if(z==EOF)return 0; if(z=='-'){neg=1;z=getchar();} for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar()); return (neg)?-res:res; } LL gll() { LL res=0;bool neg=0;char z; for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar()); if(z==EOF)return 0; if(z=='-'){neg=1;z=getchar();} for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar()); return (neg)?-res:res; } const int maxn=300100; int n; VI e[maxn]; const int up=25; int dep[maxn],jump[maxn][up+1]; int head,tail,que[maxn]; int sz[maxn],idx[maxn]; void bfs() { int i,j; dep[que[head=tail=1]=1]=1; re(j,0,up)jump[1][j]=1; while(head<=tail) { int u=que[head++]; re(i,0,SZ(e[u])-1)if(!dep[e[u][i]]) { int v=e[u][i]; dep[que[++tail]=v]=dep[u]+1; jump[v][0]=u; re(j,1,up)jump[v][j]=jump[jump[v][j-1]][j-1]; } } red(i,tail,1) { int u=que[i]; sz[u]=1; re(j,0,SZ(e[u])-1)if(dep[e[u][j]]>dep[u])sz[u]+=sz[e[u][j]]; } idx[1]=1; re(i,1,tail) { int u=que[i],tmp=0; re(j,0,SZ(e[u])-1)if(dep[e[u][j]]>dep[u]){int v=e[u][j];idx[v]=idx[u]+tmp+1,tmp+=sz[v];} } } int swim(int x,int H){for(int i=0;H;H>>=1,i++)if(H&1)x=jump[x][i];return x;} int ask_lca(int x,int y) { if(dep[x]<dep[y])swap(x,y); x=swim(x,dep[x]-dep[y]); if(x==y)return x; int i;red(i,up,0)if(jump[x][i]!=jump[y][i])x=jump[x][i],y=jump[y][i]; return jump[x][0]; } int m,h[maxn],h2[maxn]; int mark[maxn],ans[maxn]; VI to[maxn]; int ge,w[maxn]; bool cmp(int a,int b){return idx[a]<idx[b];} int top,sta[maxn]; void addedge(int u,int v){to[u].pb(v);to[v].pb(u);} void build() { int i; re(i,1,ge)to[w[i]].clear(); sort(h+1,h+m+1,cmp); ge=0; sta[top=1]=1; re(i,2,m) { while(1) { int lca=ask_lca(h[i],sta[top]); if(lca==sta[top])break; if(idx[lca]>idx[sta[top-1]]) { w[++ge]=sta[top]; addedge(sta[top],lca); sta[top]=lca; } else { addedge(sta[top],sta[top-1]); w[++ge]=sta[top--]; } } sta[++top]=h[i]; } while(top>=2)addedge(sta[top],sta[top-1]),w[++ge]=sta[top--]; w[++ge]=sta[top--]; } const int inf=0x3f3f3f3f; PII f[maxn]; int fa[maxn]; void solve() { int i,j; re(i,1,ge)fa[w[i]]=0,f[w[i]]=mark[w[i]]?mp(0,w[i]):mp(inf,0); que[head=tail=1]=1; while(head<=tail) { int u=que[head++]; re(j,0,SZ(to[u])-1)if(to[u][j]!=fa[u])fa[que[++tail]=to[u][j]]=u; } red(i,tail,2) { int u=que[i],v=fa[u]; upmin(f[v],mp(f[u].fi+dep[u]-dep[v],f[u].se)); } re(i,2,tail) { int u=que[i],v=fa[u]; upmin(f[u],mp(f[v].fi+dep[u]-dep[v],f[v].se)); } re(i,1,tail) { int x=que[i],tmp=sz[x]; re(j,0,SZ(to[x])-1)if(to[x][j]!=fa[x]) { int y=to[x][j],z=swim(y,dep[y]-dep[x]-1); tmp-=sz[z]; } ans[f[x].se]+=tmp; } re(i,2,tail) { int x=que[i],y=fa[x],dist=dep[x]-dep[y],z=swim(x,dist-1); if(f[x].se==f[y].se) ans[f[x].se]+=sz[z]-sz[x]; else { int d=(f[y].fi-f[x].fi+dist)/2.0; if((f[y].fi-f[x].fi+dist)%2==0 && f[y].se<f[x].se)d--; int u=swim(x,d); ans[f[y].se]+=sz[z]-sz[u]; ans[f[x].se]+=sz[u]-sz[x]; } } } int main() { freopen("worldtree.in","r",stdin); freopen("worldtree.out","w",stdout); int i; n=gint(); re(i,1,n-1){int x=gint(),y=gint();e[x].pb(y);e[y].pb(x);} bfs(); int Q=gint(); while(Q--) { m=gint(); re(i,1,m)mark[h2[i]=h[i]=gint()]=i; if(!mark[1])h[++m]=1; build(); solve(); re(i,1,m)if(mark[h2[i]])PF("%d ",ans[h2[i]]),ans[h2[i]]=mark[h2[i]]=0;PF("\n"); } return 0; }