zoukankan      html  css  js  c++  java
  • 【BZOJ】1086: [SCOI2005]王室联邦

    【题意】给定n个点的树,要求划分成若干大小为[B,3B]的块,满足一个块加上一个核心点后连通,求方案。n<=1000。

    【算法】树分块

    【题解】参考:PoPoQQQ 讲得很详细了,就不必听我口胡了。。。

    树分块算法的起源?用这道题的树分块算法可以实现将一棵树划分成若干[B,3B]的块。

    DFS过程中用栈记录,扫描到点x时记录top作为当前子树x的栈底(下面的点不能取)。

    如果某棵子树扫描后有>=B个点,那么直接构成一块。

    如果两棵子树扫描后才有>=B个点,那么这一块一定在[B,2B)之间,也构成一块。

    最后剩余的点加入最后一块,至多会使最后一块变成3B。

    复杂度O(n)。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=1010;
    int n,B,first[maxn],s[maxn],st[maxn],belong[maxn],tot=0,cnt=0,ans=0,top=0;
    struct edge{int v,from;}e[maxn*2];
    void insert(int u,int v){tot++;e[tot].v=v;e[tot].from=first[u];first[u]=tot;}
    void dfs(int x,int fa){
        int lim=top;
        for(int i=first[x];i;i=e[i].from)if(e[i].v!=fa){
            dfs(e[i].v,x);
            if(top-lim>=B){
                ans++;s[ans]=x;
                while(top>lim)belong[st[top--]]=ans;
            }
        }
        st[++top]=x;
    }
    int main(){
        scanf("%d%d",&n,&B);
        for(int i=1;i<n;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            insert(u,v);insert(v,u);
        }
        dfs(1,0);
        while(top)belong[st[top--]]=ans;
        printf("%d
    ",ans);
        for(int i=1;i<=n;i++)printf("%d ",belong[i]);puts("");
        for(int i=1;i<=ans;i++)printf("%d ",s[i]);
        return 0;
    }
    View Code
  • 相关阅读:
    List of the best open source software applications
    Owin对Asp.net Web的扩展
    NSwag给api加上说明
    'workspace' in VS Code
    unable to find valid certification path to requested target
    JMeter的下载以及安装使用
    exception disappear when forgot to await an async method
    Filter execute order in asp.net web api
    记录web api的request以及response(即写log)
    asp.net web api的源码
  • 原文地址:https://www.cnblogs.com/onioncyc/p/8571337.html
Copyright © 2011-2022 走看看