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':' ');
}

  妈妈,我会树分块辣~\(≧▽≦)/~啦啦啦!

posted @ 2017-03-24 21:31  SfailSth  阅读(117)  评论(0编辑  收藏  举报