BZOJ 1086 [SCOI2005]王室联邦 ——DFS
手把手教你树分块系列。
只需要记录一个栈,如果等于B的情况就弹栈,令省会为当前节点。
然后把待分块的序列不断上传即可。
考虑到有可能弹出不是自身节点的子树节点,所以记录一下当前的栈底。
DFS即可
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define maxn 2005 #define F(i,j,k) for (int i=j;i<=k;++i) int h[maxn],to[maxn],ne[maxn],en=0; void add(int a,int b) {to[en]=b;ne[en]=h[a];h[a]=en++;} int n,b,sta[maxn],top,bel[maxn],cnt,rt[maxn]; void dfs(int o,int fa) { int nbot=top; // printf("dfs on %d %d\n",o,nbot); for (int i=h[o];i>=0;i=ne[i]) if (to[i]!=fa){ dfs(to[i],o); if (top-nbot>=b) { // printf("top is %d nbot is %d\n",top,nbot); rt[++cnt]=o; while (top!=nbot) { // printf("pop\n"); bel[sta[top--]]=cnt; } } } sta[++top]=o; } int main() { memset(h,-1,sizeof h); scanf("%d%d",&n,&b); F(i,1,n-1) { int a,b; scanf("%d%d",&a,&b); add(a,b); add(b,a); } dfs(1,0); while (top) bel[sta[top--]]=cnt; printf("%d\n",cnt); F(i,1,n) printf("%d%c",bel[i],i==n?'\n':' '); F(i,1,cnt) printf("%d%c",rt[i],i==cnt?'\n':' '); }
妈妈,我会树分块辣~\(≧▽≦)/~啦啦啦!