1086: [SCOI2005]王室联邦

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

DFS每一个点,先递归子树,然后拿到子树传回的该子树中的未分组点。对所有子树的传回点合并,每每够了B个就分一块。最后把自己加入未分组点队列,传回上层。这是分块方法的一种叙述,但显然不能这么写是吧,2333。

用一个栈保存未分组的点,每次DFS一个点先记录下此时的栈顶位置,然后递归子树,每每当前栈顶到记录栈顶元素个数超过B个,就把这一段分为一块。这一段一定都是在当前点的子树里,且和当前点相邻。最后把当前点压入栈顶,返回上层即可。

这种分块的方法貌似也经常用在树上莫队等问题中。

 #include <bits/stdc++.h>

 const int siz = ;

 char buf[siz], *bit = buf;

 inline int nextInt (void) {
register int ret = ;
register int neg = ; while (*bit < '')
if (*bit++ == '-')
neg ^= true; while (*bit >= '')
ret = ret* + *bit++ - ''; return neg ? -ret : ret;
} const int maxn = + ; int n;
int m;
int tot;
int cnt;
int top;
int hd[maxn];
int nt[maxn];
int to[maxn];
int stk[maxn];
int bel[maxn];
int cap[maxn]; void divid (int u, int f) {
int bot = top; for (register int i = hd[u]; ~i; i = nt[i])
if (to[i] != f) {
divid (to[i], u);
if (top - bot >= m) {
cap[++cnt] = u;
while (top != bot)
bel[stk[top--]] = cnt;
}
} stk[++top] = u;
} signed main (void) {
fread (buf, , siz, stdin); n = nextInt ();
m = nextInt (); memset (hd, -, sizeof (hd)), tot = ; for (register int i = ; i < n; ++i) {
int x = nextInt ();
int y = nextInt ();
nt[tot] = hd[x]; to[tot] = y; hd[x] = tot++;
nt[tot] = hd[y]; to[tot] = x; hd[y] = tot++;
} divid (, -); while (top > )
bel[stk[top--]] = cnt; printf ("%d\n", cnt); for (register int i = ; i < n; ++i)
printf ("%d ", bel[i]);
printf ("%d\n", bel[n]); for (register int i = ; i < cnt; ++i)
printf ("%d ", cap[i]);
printf ("%d\n", cap[cnt]);
}

@Author: YouSiki

BZOJ 1086: [SCOI2005]王室联邦的更多相关文章

  1. 【块状树】BZOJ 1086: [SCOI2005]王室联邦

    1086: [SCOI2005]王室联邦 Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special JudgeSubmit: 826  Solved:  ...

  2. Bzoj 1086: [SCOI2005]王室联邦(分块)

    1086: [SCOI2005]王室联邦 Time Limit: 10 Sec Memory Limit: 162 MBSec Special Judge Submit: 1557 Solved: 9 ...

  3. [BZOJ 1086] [SCOI2005] 王室联邦 【树分块】

    题目链接:BZOJ - 1086 题目分析 这道题要求给树分块,使得每一块的大小在 [B, 3B] 之间,并且可以通过一个块外的节点(块根)使得整个块联通. 那么我们使用一种 DFS,维护一个栈,DF ...

  4. bzoj 1086: [SCOI2005]王室联邦 (分块+dfs)

    Description “余”人国的国王想重新编制他的国家.他想把他的国家划分成若干个省,每个省都由他们王室联邦的一个成员来管理.他的国家有n个城市,编号为1..n.一些城市之间有道路相连,任意两个不 ...

  5. bzoj 1086 [SCOI2005]王室联邦——思路

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1086 于是去看了题解. 要回溯的时候再把自己加进栈里判断.这样才能保证剩下的可以通过自己连到 ...

  6. BZOJ 1086: [SCOI2005]王室联邦 [树上分块]

    portal 题意: 树分成若干块大小在$[s,3s]$之间,每块有一个根(可以不在块内),所有点到根路径上的点都必须在块内 据说这是一个保证了块大小直径个数的科学分块方法,貌似只有本题有用  我错了 ...

  7. BZOJ 1086 [SCOI2005]王室联邦 ——DFS

    手把手教你树分块系列. 只需要记录一个栈,如果等于B的情况就弹栈,令省会为当前节点. 然后把待分块的序列不断上传即可. 考虑到有可能弹出不是自身节点的子树节点,所以记录一下当前的栈底. DFS即可 # ...

  8. 1086: [SCOI2005]王室联邦

    1086: [SCOI2005]王室联邦 Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special JudgeSubmit: 1554  Solved: ...

  9. 【BZOJ】1086: [SCOI2005]王室联邦

    http://www.lydsy.com/JudgeOnline/problem.php?id=1086 题意:n个点的树,要求分块,使得每一块的大小在[b, 3b]内且块与某个点形成的块是连通的(某 ...

随机推荐

  1. transform图形变化

    <!DOCTYPE HTML> <head> <meta charset = "utf-8"> <title>canvas</ ...

  2. Oracle数据泵(Data Dump)错误汇集

    Oracle数据泵(Data Dump)使用过程当中经常会遇到一些奇奇怪怪的错误案例,下面总结一些自己使用数据泵(Data Dump)过程当中遇到的问题以及解决方法.都是在使用过程中遇到的问题,以后陆 ...

  3. Fedora 23安装配置mysql数据库,修改初始密码及登陆

    下载MySQL5.7.9 yum仓库 wget http://dev.mysql.com/get/mysql57-community-release-fc23-7-noarch.rpm rpm -iv ...

  4. 【转】关于Java的Daemon线程的理解

    原文地址:http://www.cnblogs.com/ChrisWang/archive/2009/11/28/1612815.html 关于Java的Daemon线程的理解 网上对Java的Dae ...

  5. mac版本navicat连接oracle报错ORA-21561

    最近电脑更换成mac,很多软件都和win不一样了,正在慢慢适应,连接oracle原来用的客户端是pl/sql develop,蛋疼的是没有了mac版本, 用了navicat,具体设置如下 1.新建连接 ...

  6. linux中tar之解压和压缩常用

    我们知道在windows中解压和压缩有两个非常强大的工具winRar和国产的好压工具,在linux中也有一款强大的解压和压缩工具.那就是大名鼎鼎的tar.我们首先看看tar命令的使用格式 语法:tar ...

  7. linux basic commands

    1. man - an interface to the on-line reference manuals $man man 2. apt - advanced package tool SEE A ...

  8. 15、sql语句集,Linux 下PHP查询mysql

    一.mysql 创建数据库 mysql密码,默认没有 如果想更改的话, mysqladmin  -uroot   password  root123 登录   : [root@localhost ro ...

  9. Canvas绘图基础(一)

    简单图形绘制 矩形:描边与填充 Canvas的API提供了三个方法,分别用于矩形的清除.描边及填充 clearRect(double x, double y, double w, double h) ...

  10. 【WPF系列】基础学习-WPF设计模式概览

    引言 “设计模式”这个让程序员提起来就“酷”的东东,着实让让初学设计模式的programer自我陶醉一番.太多的经历,告诉我们“凡事都要个度,要学会适可而止”,否则过犹不及.“设计模式”也一样,切莫为 ...