zoukankan      html  css  js  c++  java
  • BZOJ1086: [SCOI2005]王室联邦

    【传送门:BZOJ1086


    简要题意:

      给出n个点,n-1条边,将这n个点分成若干个部分,每个部分都有一个中心,给出B,要求2B>=每个部分的点数>=B,是每个部分中的任意一个点到达中心所经过的点(除了最后一个点,即该部分的中心点)都必须属于该部分,求出是否能满足将n个点都分成若干个部分


    题解:

      既然题目要求该区域所有的点到根的路径上的点都属于该区域。很明显,就是一棵树,所以题意其实就是把一棵多叉树分成若干个区域,然而又不用输出最小方案,所以弱爆了。这个玩意我也不知道它算什么,应该属于dfs的范畴吧。 

      一种简单粗暴的想法就是dfs,每找到B个就分一块,但是这样连通性不能保证(一颗子树的下半截和另一棵子树的上半截组成一块)。所以我们就想:能不能从底部往上组块,每棵子树较深的部分自己成块,然后靠近根的部分组成一个大块。 

      所以我们这么做:对于一个点x,以初次访问它时,栈的栈顶作为相对栈底,每遍历完它的一个子节点所在的子树,判断此时栈顶-相对栈底得到的元素个数是否大于或等于b,若成立,那么弹栈至相对栈顶。当访问完所有子节点要回溯到x的父节点时,把x压入栈。 

      这样就可以保证连通性和块大小不会超了,最后dfs结束后肯定还会有剩余的未组成块的节点,把它们归到最后一个块就可以了。


    参考代码:

    #include<cstdio>
    #include<cstring>
    using namespace std;
    struct node
    {
        int x,y,next;
    }a[2100];int len,last[1100];
    void ins(int x,int y)
    {
        len++;
        a[len].x=x;a[len].y=y;
        a[len].next=last[x];last[x]=len;
    }
    int sta[1100],top;
    int belong[1100],tot;
    int rt[1100],n,b;
    void dfs(int fa,int x)
    {
        int now=top;
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(y!=fa)
            {
                dfs(x,y);
                if(top-now>=b)
                {
                    rt[++tot]=x;
                    while(top!=now)
                    {
                        belong[sta[top--]]=tot;
                    }
                }
            }
        }
        sta[++top]=x;
    }
    int main()
    {
        scanf("%d%d",&n,&b);
        if(n<b){printf("0
    ");return 0;}
        for(int i=1;i<n;i++)
        {
            int x,y;scanf("%d%d",&x,&y);
            ins(x,y);ins(y,x);
        }
        dfs(0,1);
        while(top) belong[sta[top--]]=tot;
        printf("%d
    ",tot);
        for(int i=1;i<=n;i++)printf("%d ",belong[i]);
        printf("
    ");
        for(int i=1;i<=tot;i++)printf("%d ",rt[i]);
        printf("
    ");
        return 0;
    }
  • 相关阅读:
    暑假日报-11
    暑假日报-10
    暑假日报-9
    暑假日报-8
    暑假日报-7
    暑假日报-6
    暑假日报-5
    暑假日报-4
    暑假日报-3
    第二次集训的每日感想
  • 原文地址:https://www.cnblogs.com/Never-mind/p/7608125.html
Copyright © 2011-2022 走看看