zoukankan      html  css  js  c++  java
  • 【BZOJ】【1086】 【SCOI2005】王室联邦

    树分块

      orz vfk && PoPoQQQ

      http://vfleaking.blog.163.com/blog/static/174807634201231684436977/
      http://blog.csdn.net/popoqqq/article/details/42772237

      这题是要把树分成一块一块的……(感觉好像不是原来理解的树分块处理操作啊……)

      每块大小B<= size <=3B ,一种简单粗暴的想法就是dfs,每找到B个就分一块,但是这样连通性不能保证(一颗子树的下半截和另一棵子树的上半截组成一块)。所以我们就想:能不能从底部往上组块,每棵子树较深的部分自己成块,然后靠近根的部分组成一个大块

      这样就可以保证连通性和块大小不会超了,最后dfs结束后肯定还会有剩余的未组成块的节点,把它们归到最后一个块就可以了。证明看vfk博客就行……

      至于实现这个“等待序列”,用的是PoPoQQQ的方法:用栈来实现,对当前节点x,它的等待序列就是bottom--top(bottom初始化为top,然后再向栈里加的元素就是他的儿子)……呃……这个自己手画一个简单的就能理解了吧……?或者脑补一下……嗯

     1 /**************************************************************
     2     Problem: 1086
     3     User: Tunix
     4     Language: C++
     5     Result: Accepted
     6     Time:12 ms
     7     Memory:1320 kb
     8 ****************************************************************/
     9  
    10 //BZOJ 1086
    11 #include<cstdio>
    12 #include<cstring>
    13 #include<cstdlib>
    14 #include<iostream>
    15 #include<algorithm>
    16 #define rep(i,n) for(int i=0;i<n;++i)
    17 #define F(i,j,n) for(int i=j;i<=n;++i)
    18 #define D(i,j,n) for(int i=j;i>=n;--i)
    19 using namespace std;
    20 void read(int &v){
    21     v=0; int sign=1; char ch=getchar();
    22     while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();}
    23     while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();}
    24     v*=sign;
    25 }
    26 /******************tamplate*********************/
    27 const int N=2015;
    28 int head[N],to[N],next[N],cnt;
    29 void add(int x,int y){
    30     to[++cnt]=y; next[cnt]=head[x]; head[x]=cnt;
    31     to[++cnt]=x; next[cnt]=head[y]; head[y]=cnt;
    32 }
    33 /********************edge***********************/
    34 int n,B,K;
    35 int st[N],top;
    36 int belong[N],root[N],tot;
    37 void dfs(int x,int fa){
    38     int bottom=top;
    39     for(int i=head[x];i;i=next[i])
    40         if (to[i]!=fa){
    41             dfs(to[i],x);
    42             if (top-bottom>=B){
    43                 root[++tot]=x;
    44                 while(top!=bottom)
    45                     belong[st[top--]]=tot;
    46             }
    47         }
    48     st[++top]=x;
    49 }
    50  
    51 int main(){
    52     read(n); read(B);
    53     int x,y;
    54     F(i,2,n){
    55         read(x); read(y);
    56         add(x,y);
    57     }
    58     dfs(1,0);
    59     while(top) belong[st[top--]]=tot;
    60     printf("%d
    ",tot);
    61     F(i,1,n) printf("%d ",belong[i]);
    62     printf("
    ");
    63     F(i,1,tot) printf("%d ",root[i]);
    64     return 0;
    65 }
    View Code

     

    1086: [SCOI2005]王室联邦

    Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special Judge
    Submit: 752  Solved: 416
    [Submit][Status][Discuss]

    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

    HINT

    Source

    [Submit][Status][Discuss]
  • 相关阅读:
    陈天桥:重点布局影音文娱业务及海内市场
    瑞信维持新浪跑赢大盘评级
    快讯:空中网第四季度净利501万美元同比涨148%
    传高盛与德劭前合伙人组5亿美元私募基金
    CodeFirst 关系创建——Fluent API配置多重关系,关闭级联删除的方法
    笔记:IE下 jquery的fadeIn与fadeOut方法失效的BUG
    Codefirst Fluent API创建关系
    javascript拖动效果的一个注意事项:拖动图片时,mousemove事件会被中断
    通过下拉菜单筛选GridPanel的数据【转】
    as3.0学习笔记——坐标轴、并记录画图所犯的两个低级错误
  • 原文地址:https://www.cnblogs.com/Tunix/p/4247955.html
Copyright © 2011-2022 走看看