從起點x到終點y,只需給x,y兩個結點加1,給LCA(x,y),fa[LCA(x,y)]減1,最后做一次從底到根的遞推即可求出每個點在多少條鏈上
樹剖:
#include<stdio.h> #include<stdlib.h> #include<vector> using namespace std; vector<int> G[300005]; int a[300005],fa[300005],deep[300005],size[300005],son[300005],top[300005],pos[300005],s[1200005]; int tot=0; void jh(int* a,int* b) { int t=*a; *a=*b; *b=t; } void dfs1(int x,int f) { int i; fa[x]=f; size[x]=1; for(i=0;i<G[x].size();i++) if(G[x][i]!=f) { deep[G[x][i]]=deep[x]+1; dfs1(G[x][i],x); size[x]+=size[G[x][i]]; if(size[G[x][i]]>size[son[x]]) son[x]=G[x][i]; } } void dfs2(int x,int t) { int i; top[x]=t; pos[x]=++tot; if(son[x]>0) dfs2(son[x],t); for(i=0;i<G[x].size();i++) if(G[x][i]!=fa[x]&&G[x][i]!=son[x]) dfs2(G[x][i],G[x][i]); } void xg(int x,int y) { s[x]++; s[y+1]--; } void tree_xg(int x,int y) { while(top[x]!=top[y]) { if(deep[top[x]]<deep[top[y]]) jh(&x,&y); xg(pos[top[x]],pos[x]); x=fa[top[x]]; } if(deep[x]>deep[y]) jh(&x,&y); xg(pos[x],pos[y]); } int main() { int n,i,x,y; scanf("%d",&n); for(i=1;i<=n;i++) scanf("%d",&a[i]); for(i=1;i<n;i++) { scanf("%d%d",&x,&y); G[x].push_back(y); G[y].push_back(x); } dfs1(1,0); dfs2(1,1); for(i=1;i<n;i++) tree_xg(a[i],a[i+1]); for(i=1;i<=n;i++) s[i]+=s[i-1]; for(i=1;i<=n;i++) { if(i==a[1]) printf("%d\n",s[pos[i]]); else printf("%d\n",s[pos[i]]-1); } return 0; }
本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。