[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;
}

猜你喜欢

转载自www.cnblogs.com/ZH-comld/p/9660735.html