![[SCOI2005]王室联邦(构造) [SCOI2005]王室联邦(构造)](https://image.shishitao.com:8440/aHR0cHM6Ly9ia3FzaW1nLmlrYWZhbi5jb20vdXBsb2FkL2NoYXRncHQtcy5wbmc%2FIQ%3D%3D.png?!?w=700&webp=1)
“余”人国的国王想重新编制他的国家。他想把他的国家划分成若干个省,每个省都由他们王室联邦的一个成员来管理。
他的国家有n个城市,编号为1..n。一些城市之间有道路相连,任意两个不同的城市之间有且仅有一条直接或间接的道路。为了防止管理太过分散,每个省至少要有B个城市,为了能有效的管理,每个省最多只有3B个城市。
每个省必须有一个省会,这个省会可以位于省内,也可以在该省外。但是该省的任意一个城市到达省会所经过的道路上的城市(除了最后一个城市,即该省省会)都必须属于该省。
一个城市可以作为多个省的省会。
聪明的你快帮帮这个国王吧!
Solution
玄学构造题。
因为省会可以不再省内,所以有一种乱搞做法。
DFS这棵树,每离开一个点,就把它加入栈内,当发现栈内元素大于等于b时,就弹到当前节点,将省会设为当前节点。
当最后剩下一些点时,我们把它放到上一个省,可以保证不超界。
这样做可以保证一定存在解。
Code
#include<iostream>
#include<cstdio>
#define N 1002
using namespace std;
int st[N],head[N],root[N],top,tot,n,b,num,co[N],u,v;
struct zzh{
int n,to;
}e[N<<];
inline void add(int u,int v){
e[++tot].n=head[u];
e[tot].to=v;
head[u]=tot;
}
void dfs(int u,int fa){
int bo=top;
for(int i=head[u];i;i=e[i].n)if(e[i].to!=fa){
int v=e[i].to;
dfs(v,u);
if(top-bo>=b){
num++;
while(top>bo)co[st[top--]]=num;
root[num]=u;
}
}
st[++top]=u;
}
int main(){
scanf("%d%d",&n,&b);
for(int i=;i<n;++i){
scanf("%d%d",&u,&v);
add(u,v);add(v,u);
}
dfs(,);
while(top)co[st[top--]]=num;
cout<<num<<endl;
for(int i=;i<=n;++i)printf("%d ",co[i]);cout<<endl;
for(int i=;i<=num;++i)printf("%d ",root[i]);
return ;
}