zoukankan      html  css  js  c++  java
  • [SCOI2005]王室联邦

    题目大意:
      给定一棵$n(nleq1000)$个结点的无根树,对其结点进行分块。对于每个块至少在树中(不一定在块中)存在一个“关键点”,使得块中所有子结点和这个“关键点”构成一个联通块。并且每个块的大小$s$满足$bleq sleq3b$。求出任意一种分块的方案。

    思路:
      贪心。
      任取一个结点作为根,从上往下DFS。用一个栈维护当前以访问完毕,还没有分配到块中的结点。对于当前以$u$为根的子树中还没有被分到块中的结点,枚举以$u$的每个子结点为根的子树,一旦其中几个未分配结点数之和大于等于$b$,就将它们分到一起,并将$u$设为关键点。将这些点从栈中删除。最后留在栈中的未分配的点和$u$一起留在栈中。
    ​  这样处理完整棵树后,肯定还会剩下一些点未分配。不难证明DFS时构造的块的大小$s$满足$bleq sleq2b$。最后剩下的点数$s$满足$sleq b$。所以可以把最后剩下的那些点合并到任意与其相邻的块中,关键点为整棵树的根。

     1 #include<stack>
     2 #include<cstdio>
     3 #include<cctype>
     4 #include<vector>
     5 inline int getint() {
     6     register char ch;
     7     while(!isdigit(ch=getchar()));
     8     register int x=ch^'0';
     9     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    10     return x;
    11 }
    12 const int N=1001;
    13 int n,b,bel[N],cap[N];
    14 std::stack<int> s;
    15 std::vector<int> e[N];
    16 inline void add_edge(const int &u,const int &v) {
    17     e[u].push_back(v);
    18     e[v].push_back(u);
    19 }
    20 void dfs(const int &x,const int &par) {
    21     const int size=s.size();
    22     for(unsigned i=0;i<e[x].size();i++) {
    23         const int y=e[x][i];
    24         if(y==par) continue;
    25         dfs(y,x);
    26         if((int)s.size()-size>=b) {
    27             cap[++cap[0]]=x;
    28             while((int)s.size()>size) {
    29                 bel[s.top()]=cap[0];
    30                 s.pop();
    31             }
    32         }
    33     }
    34     s.push(x);
    35 }
    36 int main() {
    37     n=getint(),b=getint();
    38     for(register int i=1;i<n;i++) {
    39         add_edge(getint(),getint());
    40     }
    41     dfs(1,0);
    42     while(!s.empty()) {
    43         bel[s.top()]=cap[0];
    44         s.pop();
    45     }
    46     printf("%d
    ",cap[0]);
    47     for(register int i=1;i<=n;i++) {
    48         printf("%d%c",bel[i]," 
    "[i==n]);
    49     }
    50     for(register int i=1;i<=cap[0];i++) {
    51         printf("%d%c",cap[i]," 
    "[i==cap[0]]);
    52     }
    53     return 0;
    54 }
  • 相关阅读:
    组织机构数据隔离(上级可看下级,同级屏蔽)的高效实现思路
    .NET Core 3.x 基于AspectCore实现AOP,实现事务、缓存拦截器
    .NET Core 3.x 基于Autofac的AOP缓存
    Web开发中【密码加密】详解
    python多线程 DBUtils操作数据库
    处理MariaDB Galera cluster初始化和启动报错两例
    搭建MariaDB Galera Cluster集群 10.3.8
    AzureWeb应用作为客户端携带证书访问其他链接办法
    CTF
    [KuangBin专题四]Silver Cow Party
  • 原文地址:https://www.cnblogs.com/skylee03/p/8453313.html
Copyright © 2011-2022 走看看