zoukankan      html  css  js  c++  java
  • 【块状树】BZOJ 1086: [SCOI2005]王室联邦

    1086: [SCOI2005]王室联邦

    Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special Judge
    Submit: 826  Solved: 471
    [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

      很容易想到每次搜子树
      不过好像每次搜索出的残余又要和回溯上去的子树凑
      会非常麻烦
      然后只能看题解
      copy一下
      因此我们在每次进入递归时维护一个栈底,对于当前子树来说这个栈底就是整个栈的底,栈底以下的元素不能修改或弹栈
      这样当一棵子树深搜过后由于子树内未分块节点不超过b,之前搜过的未分块节点数也不超过b,因此每块不超过2b
      那么题目为什么给了3b呢?
      深搜结束后可能会剩余一些节点,这些节点的数量不超过b,而且一定与当前分出的最后一块连通
      因此我们将剩余节点分到最后一块中,可以保证最后一块的大小不超过3b
      
     1 #include<cstdio>
     2 #include<cstring>
     3 #include<cmath>
     4 #include<algorithm>
     5 
     6 #define maxn 1001
     7 
     8 using namespace std;
     9 
    10 inline int in()
    11 {
    12     int x=0;char ch=getchar();
    13     while(ch<'0'||ch>'9')ch=getchar();
    14     while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    15     return x;
    16 }
    17 
    18 int n,l,last[maxn],tot=0,sta[maxn],top=0,father[maxn],root[maxn],cnt=0;
    19 
    20 struct ed{
    21     int to,last;
    22 }edge[maxn*2];
    23 
    24 void add(int u,int v)
    25 {
    26     edge[++tot].to=v,edge[tot].last=last[u],last[u]=tot;
    27     edge[++tot].to=u,edge[tot].last=last[v],last[v]=tot;
    28 }
    29 
    30 void dfs(int poi,int Last)
    31 {
    32     int lim=top;
    33     for(int i=last[poi];i;i=edge[i].last)if(edge[i].to!=Last){
    34         dfs(edge[i].to,poi);
    35         if(top-lim>=l)
    36         {
    37             root[++cnt]=poi;
    38             while(top!=lim)father[sta[top--]]=cnt;
    39         }
    40     }
    41     sta[++top]=poi;
    42 }
    43 
    44 int main()
    45 {
    46     int u,v;
    47     n=in();l=in();
    48     for(int i=1;i<n;i++)
    49         u=in(),v=in(),add(u,v);
    50     dfs(1,0);
    51     while(top)father[sta[top--]]=cnt;
    52     printf("%d
    ",cnt);
    53     for(int i=1;i<=n;i++)printf("%d ",father[i]);
    54     printf("
    ");
    55     for(int i=1;i<=cnt;i++)printf("%d ",root[i]);
    56     return 0;
    57 }
    View Code
      
  • 相关阅读:
    静态代码块执行顺序
    静态代码块
    方法的定义(实例与静态)
    变量的声明(实例与静态)
    static关键字
    封装2
    线程1
    数组元素的查找——二分法查找
    docker介绍、安装及要素讲解
    渗透测试基础
  • 原文地址:https://www.cnblogs.com/tuigou/p/4881282.html
Copyright © 2011-2022 走看看