洛谷 P2325 [SCOI2005]王室联邦

题目描述

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

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

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

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

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

输入输出格式

输入格式:

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

输出格式:

如果无法满足国王的要求,输出0。否则第一行输出数K,表示你给出的划分方案中省的个数,编号为1..K。第二行输出N个数,第I个数表示编号为I的城市属于的省的编号,第三行输出K个数,表示这K个省的省会的城市编号,如果有多种方案,你可以输出任意一种。

输入输出样例

输入样例#1:

8 2
1 2
2 3
1 8
8 7
8 6
4 6
6 5

输出样例#1:

3
2 1 1 3 3 3 3 2
2 1 8 
题目大意:将树分成若干块,每块大小为[B,3*B]。题解:一开始xjb做,二分分的块的大小,然后dfs分块,10分...这样做发现个问题,块不连通怎么办?就是说一个块,它的一半在一个节点左子树底部,另一半在右子树上面...然后看的题解..发现是个树上分块..还专门叫做..王室联邦分块。挖坑现学...对于以x为根的子树,如果它的大小(不包含x,这与块的连通性有关)>=B,就把它分成一个块,如果不满足,就把它们划分到等待区,累计在根节点,等待与它的兄弟子树合并成一块。如果合并上兄弟子树大小还<B,那么就一直累计想上传,向上传还有多少在等待区的节点。那么就是说,如果以x为根不包含x的子树大小>=B,直接合并成一块,否则累计到根节点,准备和它的兄弟子树合并,不能合并一直向上累计,代码中这是用栈实现的。如果累计到根,那么就把这些在等待区的节点和距离根最近的块合并。不用担心合并后节点数>3*B,因为在等待区的节点的个数一定是<B,距离根最近的块的大小是>=B,绝不会>=2*B,因为一旦>=B,立即合并为一块。所以等待区的点和距离根最近块合并相当于B+2*B,最大就是3B,不会超过。合并时递归到最底层,从树的最下面开始合并,这样避免了之前开始说的不连通的问题,之前说的不包含x是因为,如果以x为根的子树为1,2,3。如果1,2,x合并,3被x所在的块堵住,不能与其他的块合并。具体实现时,每递归到一个x,记录此时的栈顶作为相对栈底,然后再搜它的某一个子节点,如果搜完子节点后的栈顶-相对栈底>=B,将栈中栈顶到相对栈底的所有元素合并为一块,并出栈。搜完这个点的所有子树,将这个点压入栈中。最后会在栈中有剩余元素,弹出合并。代码:
#include<cstdio>
#define maxn 10005
using namespace std;

int n,b,x,y,cnt,top,sumedge;
int head[maxn],sta[maxn],belong[maxn],root[maxn];

struct Edge{
    int x,y,nxt;
    Edge(int x=0,int y=0,int nxt=0):
        x(x),y(y),nxt(nxt){}
}edge[maxn<<1];

void add(int x,int y){
    edge[++sumedge]=Edge(x,y,head[x]);
    head[x]=sumedge;
}

void dfs(int x,int fa){
    int bottom=top;
    for(int i=head[x];i;i=edge[i].nxt){
        int v=edge[i].y;
        if(v==fa)continue;
        dfs(v,x);
        if(top-bottom>=b){
            root[++cnt]=x;
            for(;top!=bottom;top--)
             belong[sta[top]]=cnt;
        }
    }
    sta[++top]=x;
}
int main(){
    scanf("%d%d",&n,&b);
    for(int i=1;i<n;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        add(x,y);add(y,x);
    }
    dfs(1,0);
    for(;top;top--)belong[sta[top]]=cnt;
    printf("%d\n",cnt);
    for(int i=1;i<=n;i++)printf("%d ",belong[i]);putchar(‘\n‘);
    for(int i=1;i<=cnt;i++)printf("%d ",root[i]);putchar(‘\n‘);
    return 0;
}
				
时间: 2024-11-14 21:42:27

洛谷 P2325 [SCOI2005]王室联邦的相关文章

洛谷.2325.[SCOI2005]王室联邦(贪心)

题目链接 比较水的题 然而.. 首先可以考虑DFS 每B个分一个块,但是这样链底不会和上边相连 于是考虑从底下开始分,即在DFS完一个点时才将其加入栈中:当子树size==B时出栈 最后在根节点可能会剩下一些未分配的点,这些点数当然<B(算上根节点<=B),分给上块就好了 感觉那么..这才2B.. #include <cstdio> #include <cctype> #define gc() getchar() const int N=1005; int n,B,En

P2325 [SCOI2005]王室联邦

思路 利用了树上莫队的分块方式,保证每个块的大小都\(\ge\)B且$\le$3B,然后证明略过 仅叙述一下算法的过程 使用一个栈,依次dfs这个点的每个子树,如果发现新增的节点数大于等于B,就分出新的一块, 最后把剩下的节点塞进最后一个块里 分块的代码 void dfs(int u,int f){ int t=S.size(); for(int i=fir[u];i;i=nxt[i]){ if(v[i]==f) continue; dfs(v[i],u); if(S.size()-t>=B){

[bzoj 1086][SCOI2005]王室联邦

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1086 [SCOI2005]王室联邦 Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special JudgeSubmit: 1876  Solved: 1144[Submit][Status][Discuss] Description “余”人国的国王想重新编制他的国家.他想把他的国家划分成若干个省,每个省都由他们王室联邦的一个成员来管理.他的国

1086: [SCOI2005]王室联邦

1086: [SCOI2005]王室联邦 Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special JudgeSubmit: 1554  Solved: 933[Submit][Status][Discuss] Description “余”人国的国王想重新编制他的国家.他想把他的国家划分成若干个省,每个省都由他们王室联邦的一个成员来管理.他的国家有n个城市,编号为1..n.一些城市之间有道路相连,任意两个不同的城市之间有且仅有一条直接或间接的道路

【块状树】BZOJ 1086: [SCOI2005]王室联邦

1086: [SCOI2005]王室联邦 Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special JudgeSubmit: 826  Solved: 471[Submit][Status][Discuss] Description “余”人国的国王想重新编制他的国家.他想把他的国家划分成若干个省,每个省都由他们王室联邦的一个成员来管理.他的国家有n个城市,编号为1..n.一些城市之间有道路相连,任意两个不同的城市之间有且仅有一条直接或间接的道路.

【BZOJ 1086】 [SCOI2005]王室联邦

1086: [SCOI2005]王室联邦 Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special Judge Submit: 599  Solved: 309 [Submit][Status] Description "余"人国的国王想重新编制他的国家.他想把他的国家划分成若干个省,每个省都由他们王室联邦的一个成员来管理.他的国家有n个城市,编号为1..n.一些城市之间有道路相连,任意两个不同的城市之间有且仅有一条直接或间接的道路.为了

洛谷P2327 [SCOI2005]扫雷 枚举 搜索

洛谷P2327 [SCOI2005]扫雷 枚举 搜索 对搜索的 一些优化 其实我们只要枚举第一行是否有地雷,根据第1行探测出的地雷数,就可以推出第二行是否有地雷 然后在根据第二行探测地雷数推出第三行的情况,这样以此类推,一直推到第 n-1 的探测结果,然后 推出第 n 行是否有地雷如果在推的过程中 使得当前的探测地雷数为 负数 ,说明这个方法是萎的, 或者这一行推完了之后,还是有雷,那也退出,最后还要判断一下第 n 行是否有地雷 1 #include <cstdio> 2 #include &

bzoj 1086: [SCOI2005]王室联邦(树上分块)

1086: [SCOI2005]王室联邦 Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special Judge Submit: 1107  Solved: 662 [Submit][Status][Discuss] Description "余"人国的国王想重新编制他的国家.他想把他的国家划分成若干个省,每个省都由他们王室联邦的一个成 员来管理.他的国家有n个城市,编号为1..n.一些城市之间有道路相连,任意两个不同的城市之间有且仅有一条

Bzoj1086 [SCOI2005]王室联邦

Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special JudgeSubmit: 1749  Solved: 1056 Description “余”人国的国王想重新编制他的国家.他想把他的国家划分成若干个省,每个省都由他们王室联邦的一个成员来管理.他的国家有n个城市,编号为1..n.一些城市之间有道路相连,任意两个不同的城市之间有且仅有一条直接或间接的道路.为了防止管理太过分散,每个省至少要有B个城市,为了能有效的管理,每个省最多只有3B个城市