[SCOI 2005]王室联邦
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
1 2
2 3
1 8
8 7
8 6
4 6
6 5
Sample Output
2 1 1 3 3 3 3 2
2 1 8
题解(转载)
大神们都一句话带过。
在网上扒了老长时间,才领悟。
整理一下,发给大家。
先说一个问题:
如果在当前节点,其有两个儿子。
在左儿子的子树中搜得的节点数是$a-1$的话,这时候我们去搜右儿子,不妨假设右儿子为根的子树是一条长为$10000$的链。
那么显然最下面的叶节点跟左儿子代表的子树是在同一块中的,这显然碎成渣了。
所以每一次搜到一个节点,我们都要把当前的栈的指针当做该节点的相对栈底,这样的话就能避免这个问题。
首先以任意节点为根$DFS$,$DFS$的任务是解决以当前节点为根的子树(不包括当前节点)中的节点的归属,并汇报不知道去向何方者。
具体做法是:
对于每个正在处理的节点$v$,定义一个等待序列,扫一遍它的孩子。在扫的时候,假设当前$for$循环正在处理的是孩子$u$,$DFS(u)$,然后把传回来的等待序列加到$v$的等待序列中。如果$v$的等待序列节点数超过了$B$,那么就让等待队列中的节点组成一个省,省会是$v$,但$v$不划入那个省中。最后,$for$循环结束,把$v$加入到等待序列中,$return$。在主函数中接收$DFS$的返回值,若等待序列为空,皆大欢喜;但事实上,等待序列不可能为空。
那么等待序列中的节点数一定不超过$B + 1$,怎么办?答案就是放在上一个被划分出的省中去,那么上一个被划分出的省一定$<=2B - 1$,而现在最后无家可归的节点数一定$<= B + 1$,所以放在上一个被划分出的省中去节点数一定不超过$3B$!而且最后被划分出来的省一定和最后无家可归的节点中的某一个相邻!那么考虑什么时候会出现无解呢?答案就是我们找不到“上一个被划分出的省”
//It is made by Awson on 2017.9.28
#include <set>
#include <map>
#include <cmath>
#include <ctime>
#include <queue>
#include <stack>
#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define LL long long
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
#define sqr(x) ((x)*(x))
using namespace std;
const int N = ;
void read(int &x) {
char ch; bool flag = ;
for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || ); ch = getchar());
for (x = ; isdigit(ch); x = (x<<)+(x<<)+ch-, ch = getchar());
x *= -*flag;
} int n, b, u, v;
int sta[N+], top;
int cnt, belong[N+], root[N+];
struct tt {
int to, next;
}edge[*N+];
int path[N+], tot; void add(int u, int v) {
edge[++tot].to = v;
edge[tot].next = path[u];
path[u] = tot;
}
void dfs(int u, int fa) {
int bot = top;
for (int i = path[u]; i; i = edge[i].next)
if (edge[i].to != fa) {
dfs(edge[i].to, u);
if (top-bot >= b) {
root[++cnt] = u;
while (top != bot) belong[sta[top--]] = cnt;
}
}
sta[++top] = u;
}
void work() {
read(n), read(b);
for (int i = ; i < n; i++) {
read(u), read(v);
add(u, v); add(v, u);
}
dfs(, );
while (top) belong[sta[top--]] = cnt;
printf("%d\n", cnt);
for (int i = ; i <= n; i++) printf("%d ", belong[i]);
printf("\n");
for (int i = ; i <= cnt; i++) printf("%d ", root[i]);
printf("\n");
}
int main() {
work();
return ;
}
[SCOI 2005]王室联邦的更多相关文章
- BZOJ1086 [SCOI2005]王室联邦 【dfs + 贪心】
题目 "余"人国的国王想重新编制他的国家.他想把他的国家划分成若干个省,每个省都由他们王室联邦的一个成 员来管理.他的国家有n个城市,编号为1..n.一些城市之间有道路相连,任意两 ...
- BZOJ 1086: [SCOI2005]王室联邦
1086: [SCOI2005]王室联邦 Time Limit: 10 Sec Memory Limit: 162 MBSec Special JudgeSubmit: 1399 Solved: ...
- 【BZOJ-1086】王室联邦 分块 + 块状树
1086: [SCOI2005]王室联邦 Time Limit: 10 Sec Memory Limit: 162 MBSec Special JudgeSubmit: 1094 Solved: ...
- BZOJ1086 [SCOI2005]王室联邦
Description “余”人国的国王想重新编制他的国家.他想把他的国家划分成若干个省,每个省都由他们王室联邦的一个成 员来管理.他的国家有n个城市,编号为1..n.一些城市之间有道路相连,任意两个 ...
- 【块状树】BZOJ 1086: [SCOI2005]王室联邦
1086: [SCOI2005]王室联邦 Time Limit: 10 Sec Memory Limit: 162 MBSec Special JudgeSubmit: 826 Solved: ...
- 【BZOJ】【1086】 【SCOI2005】王室联邦
树分块 orz vfk && PoPoQQQ http://vfleaking.blog.163.com/blog/static/174807634201231684436977/ h ...
- 1086: [SCOI2005]王室联邦
1086: [SCOI2005]王室联邦 Time Limit: 10 Sec Memory Limit: 162 MBSec Special JudgeSubmit: 1554 Solved: ...
- bzoj 1086: [SCOI2005]王室联邦 (分块+dfs)
Description “余”人国的国王想重新编制他的国家.他想把他的国家划分成若干个省,每个省都由他们王室联邦的一个成员来管理.他的国家有n个城市,编号为1..n.一些城市之间有道路相连,任意两个不 ...
- [SCOI2005]王室联邦(构造)
“余”人国的国王想重新编制他的国家.他想把他的国家划分成若干个省,每个省都由他们王室联邦的一个成员来管理. 他的国家有n个城市,编号为1..n.一些城市之间有道路相连,任意两个不同的城市之间有且仅有一 ...
随机推荐
- Beta Scrum Day 6
听说
- 20155227 实现mypwd
20155227 实现mypwd 1 学习pwd命令 2 研究pwd实现需要的系统调用(man -k; grep),写出伪代码 3 实现mypwd 4 测试mypwd 课堂学习笔记 实现mypwd 在 ...
- 201621123060《JAVA程序设计》第十三周学习总结
1. 本周学习总结 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 2. 为你的系统增加网络功能(购物车.图书馆管理.斗地主等)-分组完成 为了让你的系统可以被多个用户通过网 ...
- Python split()方法
Python split()方法 描述 Python split()通过指定分隔符对字符串进行切片,如果参数num 有指定值,则仅分隔 num 个子字符串 语法 split()方法语法: str.sp ...
- Struts2之配置文件中Action的详细配置
在Struts2之配置一文中,我们知道一个struts配置文件可以分为三部分:常量配置 包含其他配置文件的配置 Action配置 . 这其中 常量配置 和 包含其他配置文件的配置 二 ...
- 09_Python定义方法_Python编程之路
有关Python判断与循环的内容我们上几节已经跟大家一起学习了,这一节我们主要针对def 做一个讲解 def 定义一个方法 在项目编程中,我们往往要做很多重复的事,比如一个排序的功能(当然Python ...
- Leetcode:Two Sum
原题:https://leetcode.com/problems/two-sum/ 尝试了两种方法: 方法一: var twoSum = function(nums, target) { for(va ...
- python之celery的使用(一)
前段时间需要使用rabbitmq做写缓存,一直使用pika+rabbitmq的组合,pika这个模块虽然可以很直观地操作rabbitmq,但是官方给的例子太简单,对其底层原理了解又不是很深,遇到很多坑 ...
- maven 每次update后影响接口实现类的问题
遇到maven每次update后,就会更改eclipse中java Compiler中的jdk compliance版本 <plugin> <groupId>org.apach ...
- 怎样使用下载的bootstrap模板?
核心文件bootstarp.css和bootstarp.js导入到页面,然后看着官网的代码复制进去用就可以了.网上是有不少教程的.实际上就是加class 属性 ,如:http://www.runoob ...