• [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;
    }
  • 相关阅读:
    3dsmaxunity3d
    libav android移植交叉编译
    libav 由显卡中读取数据制作视频
    超详细mysql left join,right join,inner join用法分析
    VC常见入门问题总结
    c#皮肤美化
    论坛
    vc中文件的读写操作
    MySQL的mysqldump工具的基本用法
    perl产生随机数
  • 原文地址:https://www.cnblogs.com/ZH-comld/p/9660735.html
Copyright © 2020-2023  润新知