虚树模板
講解博客:https://blog.csdn.net/weixin_37517391/article/details/82744605
用法:可以將樹中的關鍵節點單獨拎出來構造出一棵小于等于 min( n , 2 * k ) 個節點的虛樹,其中 n 為原樹節點個數,k 為關鍵節點個數
代碼:
const int N=1e5+100;struct virtual_tree {//原樹部分 struct{int to,next;}edge[N<<1];int head[N],cnt,deep[N],dp[N][20],limit;//樹上倍增static int L[N],R[N],dfn;//dfs序 static bool cmp(int x,int y){return L[x]<L[y];}void addedge(int u,int v){edge[cnt].to=v;edge[cnt].next=head[u];head[u]=cnt++;}void dfs(int u,int fa,int dep){L[u]=++dfn;deep[u]=dep;dp[u][0]=fa;for(int i=1;i<=limit;i++)dp[u][i]=dp[dp[u][i-1]][i-1];for(int i=head[u];i!=-1;i=edge[i].next){int v=edge[i].to;if(v!=fa)dfs(v,u,dep+1);}R[u]=dfn;}int LCA(int x,int y){if(deep[x]<deep[y])swap(x,y);for(int i=limit;i>=0;i--)if(deep[x]-deep[y]>=(1<<i))x=dp[x][i];if(x==y)return x;for(int i=limit;i>=0;i--)if(dp[x][i]!=dp[y][i]){x=dp[x][i];y=dp[y][i];}return dp[x][0];}void init(int n){memset(head,-1,sizeof(head));cnt=dfn=0;limit=log2(n)+1;for(int i=1;i<n;i++){int u,v;scanf("%d%d",&u,&v);addedge(u,v);addedge(v,u);}}//虛樹部分 vector<int>node[N];vector<int>ver;int Stack[N];void build(){sort(ver.begin(),ver.end(),cmp);int sz=ver.size()-1;for(int i=0;i<sz;i++)ver.push_back(LCA(ver[i],ver[i+1]));sort(ver.begin(),ver.end(),cmp);ver.erase(unique(ver.begin(),ver.end()),ver.end());int top=0;Stack[++top]=ver[0];for(int i=1;i<ver.size();i++){while(top&&R[Stack[top]]<L[ver[i]])top--;if(top)node[Stack[top]].push_back(ver[i]);Stack[++top]=ver[i];}}void clear(){for(int i=0;i<ver.size();i++)node[ver[i]].clear();} }tree;另一份模板:(只需要用到 dfn 和 deep)
int st[N<<1],top,ver[N<<1],dfn[N],k;bool cmp(int a,int b) {return dfn[a]<dfn[b]; }void build() {int top=0;st[0]=1;sort(ver+1,ver+k+1,cmp);for(int i=1;i<=k;i++){if(!top){st[++top]=ver[i];continue;}int x=ver[i],y=lca(x,st[top]);if(y==st[top])continue;while(top&&dfn[st[top-1]]>=dfn[y]){add(st[top-1],st[top]);top--;}if(dfn[y]!=dfn[st[top]]){add(y,st[top]);st[top]=y;}st[++top]=x;}while(top){add(st[top-1],st[top]);top--;} }?
總結
- 上一篇: CodeForces - 613D Ki
- 下一篇: 牛客 - 血压游戏(虚树+dp)