[bzoj1086][SCOI2005][王室联邦] (树分块)

Description

  “余”人国的国王想重新编制他的国家。他想把他的国家划分成若干个省,每个省都由他们王室联邦的一个成
员来管理。他的国家有n个城市,编号为1..n。一些城市之间有道路相连,任意两个不同的城市之间有且仅有一条
直接或间接的道路。为了防止管理太过分散,每个省至少要有B个城市,为了能有效的管理,每个省最多只有3B个
城市。每个省必须有一个省会,这个省会可以位于省内,也可以在该省外。但是该省的任意一个城市到达省会所经
过的道路上的城市(除了最后一个城市,即该省省会)都必须属于该省。一个城市可以作为多个省的省会。聪明的
你快帮帮这个国王吧!

Input

  第一行包含两个数N,B(1<=N<=1000, 1 <= B <= N)。接下来N-1行,每行描述一条边,包含两个数,即这
条边连接的两个城市的编号。

Output

  如果无法满足国王的要求,输出0。否则输出数K,表示你给出的划分方案中省的个数,编号为1..K。第二行输
出N个数,第I个数表示编号为I的城市属于的省的编号,第三行输出K个数,表示这K个省的省会的城市编号,如果
有多种方案,你可以输出任意一种。

Sample Input

8 2 
1 2 
2 3 
1 8 
8 7 
8 6 
4 6 
6 5

Sample Output

3 
2 1 1 3 3 3 3 2 
2 1 8

Solution

新技能get,树分块

大致做法如下,深搜整棵树,将沿路点入栈,若栈大小超过了B,则将超过B的部分点弹出,加入一个块,以当前点作为首都

最后把为出栈元素再加入一个栈

这样做块的大小一定不会超过3B

0ms的程序,rank31

//Kaiba_Seto 20170117
//orz cjkmao
#include <stdio.h>
#include <string.h>
#define MaxN 1010
#define MaxBuf 1<<22
#define RG register
#define inline __inline__ __attribute__((always_inline))
#define Blue() ((S == T&&(T=(S=B)+fread(B,1,MaxBuf,stdin),S == T)) ? 0 : *S++)

char B[MaxBuf],*S=B,*T=B;

template<class Type>inline void Rin(RG Type &x) {
    x=0;RG Type c=Blue(),f=1;
    for(; c<48||c>57; c=Blue())
        if(c==45)f=-1;
    for(; c>47&&c<58; c=Blue())
        x=(x<<1)+(x<<3)+c-48;
    x*=f; }

bool vis[MaxN];

int n,_b,_pb[MaxN],_pb_top,belong[MaxN],block_cnt,block_cap[MaxN];

struct p {
    p *n; int t; }*f[MaxN];

inline void link(RG int x,RG int y) {
    static p mem[MaxN<<1],*top=mem;
    *++top=(p) {f[x],y},f[x]=top;
    *++top=(p) {f[y],x},f[y]=top; }

void dfs(RG int x) {
    vis[x]=1;
    RG size_t status=_pb_top;
    for(RG p *j=f[x]; j; j=j->n)
        if(!vis[j->t]) {
            dfs(j->t);
            if(_pb_top-status >= _b) {
                block_cap[++block_cnt]=x;
                while(_pb_top != status) {
                    RG int t=_pb[_pb_top--];
                    belong[t]=block_cnt; } } }
    _pb[++_pb_top]=x; }

inline void block_solve() {
    dfs(1);
    while(_pb_top) {
        RG int t=_pb[_pb_top--];
        belong[t]=block_cnt; } }

int main() {
    Rin(n),Rin(_b);
    for(RG int i=1; i<n; i++) {
        RG int x,y;
        Rin(x),Rin(y);
        link(x,y); }
    block_solve();
    printf("%d\n",block_cnt);
    for(RG int i=1; i<=n; i++)
        printf("%d%c",belong[i],i==n?'\n':' ');
    for(RG int i=1; i<=block_cnt; i++)
        printf("%d%c",block_cap[i],i==block_cnt?'\n':' ');
    fclose(stdin);
    return 0; }

 

posted @ 2017-01-17 08:44  keshuqi  阅读(...)  评论(... 编辑 收藏