1086: [SCOI2005]王室联邦

来源:互联网 发布:json fromobject jar 编辑:程序博客网 时间:2024/04/28 06:17

1086: [SCOI2005]王室联邦

Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special Judge
Submit: 1228  Solved: 747
[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,假设我们当前跑到了节点u

维护一个等待栈,栈内元素为尚未确定省份的点

每当栈内元素大于等于b,就把栈内所有元素划为一个省份,清空栈

倘若u的子树都递归完了,,还剩下一些没有确定省份的点,

把u入栈,并将栈内所有元素移交给u的父亲,处理方式同样

移交的栈的大小必不超过b而等待栈的大小小于b,因而每次构建的栈大小都是[b,2b)

最后我们递归到根,然后出去了

这时栈内一定剩下不超过b个元素,就划归到上一个省,,,显然,不超过3b的


#include<iostream>#include<cstdio>#include<queue>#include<vector>#include<bitset>#include<algorithm>#include<cstring>#include<map>#include<stack>#include<set>#include<cmath>#include<ext/pb_ds/priority_queue.hpp>using namespace std;const int maxn = 1010;int n,b,cnt,top,s[maxn],belong[maxn],root[maxn];vector <int> v[maxn];void dfs(int x,int from){int k = top;for (int i = 0; i < v[x].size(); i++) {int to = v[x][i];if (to == from) continue;dfs(to,x);if (top - k >= b) {root[++cnt] = x;while (top != k) {belong[s[top]] = cnt;--top;}}}s[++top] = x;}int main(){#ifdef DMCfreopen("DMC.txt","r",stdin);#endifcin >> n >> b;for (int i = 1; i < n; i++) {int x,y; scanf("%d%d",&x,&y);v[x].push_back(y);v[y].push_back(x);}dfs(1,0);while (top) {belong[s[top]] = cnt;--top;}printf("%d\n",cnt);for (int i = 1; i < n; i++) printf("%d ",belong[i]);printf("%d\n",belong[n]);for (int i = 1; i <= cnt; i++) printf("%d ",root[i]);return 0;}


0 0
原创粉丝点击