博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[SCOI2005]王室联邦
阅读量:6240 次
发布时间:2019-06-22

本文共 1359 字,大约阅读时间需要 4 分钟。

题目大意:

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

思路:

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

1 #include
2 #include
3 #include
4 #include
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
s;15 std::vector
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
=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

 

转载于:https://www.cnblogs.com/skylee03/p/8453313.html

你可能感兴趣的文章