[SCOI2005]王室联邦(构造)
“余”人国的国王想重新编制他的国家。他想把他的国家划分成若干个省,每个省都由他们王室联邦的一个成员来管理。
他的国家有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<<1]; 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=1;i<n;++i){ scanf("%d%d",&u,&v); add(u,v);add(v,u); } dfs(1,0); while(top)co[st[top--]]=num; cout<<num<<endl; for(int i=1;i<=n;++i)printf("%d ",co[i]);cout<<endl; for(int i=1;i<=num;++i)printf("%d ",root[i]); return 0; }