• 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
     
     
    正解:树上分块
    解题报告:
      这道题只需要随意输出一组方案就可以了,似乎可以乱搞。。。
      考虑树上分块,每当扫到发现子树结点已经不小于B了,那么考虑把他们直接划成一个省,并且以当前根结点为省会即可。
      并且把子树中所有结点划到一个块中,用栈维护一下就可以了。那么最后会剩下一些结点,随便丢哪个块都是可以的,只要发现路上有一个点已经被划成某个块中,那么把接下来的子树中的点也都划成这个块即可,这样才能保证题目要求。
     
     1 //It is made by jump~
     2 #include <iostream>
     3 #include <cstdlib>
     4 #include <cstring>
     5 #include <cstdio>
     6 #include <cmath>
     7 #include <algorithm>
     8 #include <ctime>
     9 #include <vector>
    10 #include <queue>
    11 #include <map>
    12 #include <set>
    13 #ifdef WIN32   
    14 #define OT "%I64d"
    15 #else
    16 #define OT "%lld"
    17 #endif
    18 using namespace std;
    19 typedef long long LL;
    20 const int MAXN = 1011;
    21 int first[MAXN],to[MAXN*2],next[MAXN*2],size[MAXN];
    22 int n,k,ecnt,B,cnt;
    23 int que[MAXN],top;
    24 int cap[MAXN];
    25 int belong[MAXN];
    26 
    27 inline int getint()
    28 {
    29        int w=0,q=0;
    30        char c=getchar();
    31        while((c<'0' || c>'9') && c!='-') c=getchar();
    32        if (c=='-')  q=1, c=getchar();
    33        while (c>='0' && c<='9') w=w*10+c-'0', c=getchar();
    34        return q ? -w : w;
    35 }
    36 
    37 inline void dfs(int x,int fa){
    38     que[++top]=x;
    39     for(int i=first[x];i;i=next[i]) {
    40     int v=to[i];
    41     if(v==fa) continue;
    42     dfs(v,x);
    43     if(size[x]+size[v]>=B) {//子树超过范围
    44         cap[++k]=x;//直接以子树为省,根为省会
    45         while(que[top]!=x) belong[que[top--]]=k;
    46         size[x]=0;
    47     }else size[x]+=size[v];
    48     }
    49     size[x]++;
    50 }
    51 
    52 inline void paint(int x,int fa,int col){//剩下的随便放
    53     if(!belong[x])  belong[x]=col;
    54     else col=belong[x];//练到当前块下
    55     for(int i=first[x];i;i=next[i]) {
    56     if(to[i]!=fa) paint(to[i],x,col);
    57     }
    58 }
    59 
    60 inline void work(){
    61     n=getint(); B=getint(); int x,y;
    62     for(int i=1;i<n;i++) {
    63     x=getint(); y=getint();
    64     next[++ecnt]=first[x]; first[x]=ecnt; to[ecnt]=y;
    65     next[++ecnt]=first[y]; first[y]=ecnt; to[ecnt]=x;
    66     }
    67     dfs(1,0);
    68     if(!k) cap[++k]=1;
    69     paint(x,0,k);
    70     printf("%d
    ",k);
    71     for(int i=1;i<=n;i++) printf("%d ",belong[i]);printf("
    ");
    72     for(int i=1;i<=k;i++) printf("%d ",cap[i]);
    73 }
    74 
    75 int main()
    76 {
    77   work();
    78   return 0;
    79 }
  • 相关阅读:
    删除查询出以外的数据
    查询头3条
    查询共多少条记录
    Linq查询非泛型集合要指定Student类型(比如List)
    Linq to 泛型集合查询集合包括大写M和年龄小于等于18
    LINQ查询字符串判断是否大写
    LINQ查询数组里面是否包含某值
    Lambda表达式
    构建之法(四)
    构建之法(三)
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/5712825.html
Copyright © 2020-2023  润新知