cf1286B——构造,启发式合并
Posted zsben991126
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了cf1286B——构造,启发式合并相关的知识,希望对你有一定的参考价值。
/* 思路:借鉴 dsu on tree,自底往上进行合并 给每个叶子结点赋初始值为1,每个结点依次合并每个儿子 为了防止冲突,子树在被并入当前结点时,所有结点都要重新编号 最后把当前结点插到子树里去,由于又插进了一个结点,所以再重新编号一次 每个最多被重新编号n次,复杂度O(n^2) */ #include<bits/stdc++.h> #include<vector> using namespace std; #define N 2005 int n,p[N],c[N],id[N]; vector<int>G[N]; vector<int> subtree[N]; int root; void dfs(int u,int pre){ if(G[u].size()==1 && pre==0){ subtree[u].push_back(u); id[u]=1;return; } for(auto v:G[u]) if(v!=pre)dfs(v,u); int tot=0; for(auto v:G[u])if(v!=pre){ for(auto x:subtree[v]){ subtree[u].push_back(x); id[x]+=tot; } tot+=subtree[v].size(); subtree[v].clear(); } stack<int>stk; while(stk.size())stk.pop(); while(subtree[u].size()>=c[u]){ stk.push(subtree[u].back()); subtree[u].pop_back(); } subtree[u].push_back(u); id[u]=c[u]; while(stk.size()){ int now=stk.top();stk.pop(); id[now]++; subtree[u].push_back(now); } } int size[N]; void getsize(int u,int pre){ size[u]=1; for(auto v:G[u]){ if(v==pre)continue; getsize(v,u);size[u]+=size[v]; } } int main(){ cin>>n; for(int i=1;i<=n;i++){ cin>>p[i]>>c[i]; c[i]++; G[i].push_back(p[i]); G[p[i]].push_back(i); if(p[i]==0)root=i; } getsize(root,0); for(int i=1;i<=n;i++) if(size[i]<c[i]){ puts("NO");return 0; } dfs(root,0); puts("YES"); for(int i=1;i<=n;i++)cout<<id[i]<<" "; }
以上是关于cf1286B——构造,启发式合并的主要内容,如果未能解决你的问题,请参考以下文章
#线段树合并树上启发式合并#CF600E Lomsat gelral
CF 600 E Lomsat gelral —— 树上启发式合并