P2325 [SCOI2005]王室联邦 解题报告

P2325 [SCOI2005]王室联邦

题目描述

“余”人国的国王想重新编制他的国家。他想把他的国家划分成若干个省,每个省都由他们王室联邦的一个成员来管理。

他的国家有\(n\)个城市,编号为\(1\dots n\)。一些城市之间有道路相连,任意两个不同的城市之间有且仅有一条直接或间接的道路。为了防止管理太过分散,每个省至少要有\(B\)个城市,为了能有效的管理,每个省最多只有\(3B\)个城市。

每个省必须有一个省会,这个省会可以位于省内,也可以在该省外。但是该省的任意一个城市到达省会所经过的道路上的城市(除了最后一个城市,即该省省会)都必须属于该省。

一个城市可以作为多个省的省会。

聪明的你快帮帮这个国王吧!

输入输出格式

输入格式:

第一行包含两个数\(N\)\(B\)\(1\le N\le 1000, 1\le B \le N\))。接下来\(N-1\)行,每行描述一条边,包含两个数,即这条边连接的两个城市的编号。

输出格式:

如果无法满足国王的要求,输出\(0\)

否则第一行输出数\(K\),表示你给出的划分方案中省的个数,编号为\(1\dots K\)

第二行输出\(N\)个数,第\(i\)个数表示编号为\(i\)的城市属于的省的编号。

第三行输出\(K\)个数,表示这\(K\)个省的省会的城市编号,如果有多种方案,你可以输出任意一种。


这里扔一个偷来的图片,顺便问下这是哪个ppt呀

一种树分块的方法...我还不知道这东西的实际意义

记录当前点的栈顶,然后每遍历完一个儿子,如果栈顶-记录点的个数大于\(B\),就以这个点为首都扔出来,最后把这个点加进去。

如果最后有剩,放到最后一个点形成的首都里就行了,可以证明不超过\(3B\)


Code:

#include <cstdio>
const int N=1e3+10;
int head[N],to[N<<1],Next[N<<1],cnt;
int n,B,s[N],rt[N],bel[N],tot,top;
void add(int u,int v)
{
    to[++cnt]=v,Next[cnt]=head[u],head[u]=cnt;
}
void dfs(int now,int fa)
{
    int bot=top;
    for(int v,i=head[now];i;i=Next[i])
        if((v=to[i])!=fa)
        {
            dfs(v,now);
            if(top-bot>=B)
            {
                rt[++tot]=now;
                while(top!=bot) bel[s[top--]]=tot;
            }
        }
    s[++top]=now;
}
int main()
{
    scanf("%d%d",&n,&B);
    for(int u,v,i=1;i<n;i++) scanf("%d%d",&u,&v),add(u,v),add(v,u);
    dfs(1,0);
    while(top) bel[s[top--]]=tot;
    printf("%d\n",tot);
    for(int i=1;i<=n;i++) printf("%d ",bel[i]);
    puts("");
    for(int i=1;i<=tot;i++) printf("%d ",rt[i]);
    return 0;
}

2019.1.6

猜你喜欢

转载自www.cnblogs.com/ppprseter/p/10229917.html