zoukankan      html  css  js  c++  java
  • [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
    ",block_cnt);
        for(RG int i=1; i<=n; i++)
            printf("%d%c",belong[i],i==n?'
    ':' ');
        for(RG int i=1; i<=block_cnt; i++)
            printf("%d%c",block_cap[i],i==block_cnt?'
    ':' ');
        fclose(stdin);
        return 0; }
  • 相关阅读:
    BZOJ 1051: [HAOI2006]受欢迎的牛
    BZOJ 3668: [Noi2014]起床困难综合症
    BZOJ 4395: [Usaco2015 dec]Switching on the Lights
    BZOJ 2763: [JLOI2011]飞行路线
    Bzoj 3196 Tyvj 1730 二逼平衡树
    BZOJ 2407: 探险/4398: 福慧双修
    BZOJ 3040: 最短路(road)
    BZOJ 2809: [Apio2012]dispatching
    BZOJ 1651: [Usaco2006 Feb]Stall Reservations 专用牛棚
    BZOJ 4590: [Shoi2015]自动刷题机
  • 原文地址:https://www.cnblogs.com/keshuqi/p/6291671.html
Copyright © 2011-2022 走看看