zoukankan      html  css  js  c++  java
  • 洛谷P2325 [SCOI2005]王室联邦

    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

    说明

    感谢@FlierKing提供spj

    题解

    dfs过程中每退出一个点,将这个点加入栈中。对于某个节点,如果他的一些子树能够构成>=B的块,则将他们作为一个快。剩余的一部分加入最后一个块中。可以证明,每次形成的块大小一定大于等于B小于2B,而剩余的一部分大小小于等于B,最后一个快不会超过3B
    这种分块方法,块内不一定联通

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cstdlib>
    #include <iostream>
    #include <bitset>
    #include <cmath> 
    void swap(int &a, int &b){int tmp = a;a = b, b = tmp;}
    int max(int a, int b){return a > b ? a : b;}
    int min(int a, int b){return a < b ? a : b;}
    void read(int &x)
    {
    	x = 0;char ch = getchar(), c = ch;
    	while(ch < '0' || ch > '9') c = ch, ch = getchar();
    	while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar();
    	if(c == '-') x = -x;
    }
    
    const int INF = 0x3f3f3f3f;
    const int MAXN = 1000 + 10;
    
    struct Edge
    {
    	int u, v, nxt;
    	Edge(int _u, int _v, int _nxt){u = _u, v = _v, nxt = _nxt;}
    	Edge(){}
    }edge[MAXN << 1];
    int head[MAXN], cnt, n;
    
    void insert(int a, int b)
    {
    	edge[++ cnt] = Edge(a, b, head[a]), head[a] = cnt;
    	edge[++ cnt] = Edge(b, a, head[b]), head[b] = cnt;
    }
    
    int belong[MAXN], stack[MAXN], top, cap[MAXN], B, num;
    
    void dfs(int x, int pre)
    {
    	int now = top;
    	for(int pos = head[x];pos;pos = edge[pos].nxt)
    	{
    		int v = edge[pos].v;
    		if(pre == v) continue;
    		dfs(v, x);
    		if(top - now >= B)
    			for(++ num, cap[num] = x;now < top;-- top)
    				belong[stack[top]] = num;
    	}
    	stack[++ top] = x;
    }
    
    int main()
    {
    	read(n), read(B);
    	for(int i = 1;i < n;++ i)
    	{
    		int tmp1, tmp2;
    		read(tmp1), read(tmp2);
    		insert(tmp1, tmp2);
    	}
    	dfs(1, 0);
    	for(int i = 1;i <= n;++ i)
    		if(belong[i] == 0)
    			belong[i] = num;
    	printf("%d
    ", num);
    	for(int i = 1;i <= n;++ i)
    		printf("%d ", belong[i]);
    	printf("
    ");
    	for(int i = 1;i <= num;++ i)
    		printf("%d ", cap[i]);
    	return 0;
    } 
    
  • 相关阅读:
    (深入理解计算机系统)内存对齐
    (深入理解计算机系统)AT&T汇编指令
    (深入理解计算机系统)编译,链接和装载
    (C)struct结构体指针
    (linux)BSP板级支持包开发理解
    TortoiseSVN使用笔记
    (linux)idr(integer ID management)机制
    (linux)struct inode 和 struct file
    cygwin使用笔记
    Zookeeper学习总结
  • 原文地址:https://www.cnblogs.com/huibixiaoxing/p/11233976.html
Copyright © 2011-2022 走看看