[BZOJ 1086][SCOI 2005] 王室联邦

空扰寡人 提交于 2020-02-01 17:59:49

题目大意

一个 (n) 个节点的树,将点划分为若干块,每块的大小最少为 (b),最大为 (3b)。同时,为每一块选一个节点,使得块中所有节点到这个特殊节点的路径上的点(特殊节点本身除外)均在这一块内。给定树,输出任意一种划分方案(可能无解)。

(1 leqslant n leqslant 1,000, 1 leqslant b leqslant n)

题目链接

BZOJ 1086

CodeVS 2450

题解

当且仅当 (b > n) 时无解。有解时,对树进行 dfs,每当某一点的一些子树大小超过了 (b),就分成一块,并令该点为新分的块的特殊节点。dfs 后,可能会剩一些节点没有块,再 dfs 一遍划给旁边的块就行了。

代码

一开始交的代码没有特判无解,居然就 AC 了。。。

那堆 DBG 是因为一开始把 stack 写成了 queue。。。

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
#include <stack>const int MAXN = 1005;struct ;struct Node {	Edge *firstEdge;	int belong, size, id;} N[MAXN];struct  {	Node *u, *v;	Edge *next;	Edge(Node *u, Node *v) : u(u), v(v), next(u->firstEdge) {}};int cap[MAXN], proCnt;void addEdge(int u, int v) {#ifdef DBG	printf("edge: %d <--> %dn", u, v);#endif	N[u].firstEdge = new Edge(&N[u], &N[v]);	N[v].firstEdge = new Edge(&N[v], &N[u]);}int b;void dfs(Node *u, Node *fa = NULL) {#ifdef DBG	printf("dfs(%d), fa = %dn", u->id, fa ? fa->id : 0);#endif	static std::stack<Node *> s;	s.push(u);	for (Edge *e = u->firstEdge; e; e = e->next) {#ifdef DBG		printf("dfs-edge: %d --> %dn", u->id, e->v->id);#endif		if (e->v == fa) continue;		dfs(e->v, u);#ifdef DBG		printf("dfs(%d)size = %dn", u->id, u->size);#endif				if (u->size + e->v->size >= b) {			u->size = 0;			cap[++proCnt] = u->id;			while (s.top() != u) s.top()->belong = proCnt, s.pop();		} else u->size += e->v->size;	}	u->size++;#ifdef DBG	printf("dfs-end(%d)n", u->id);#endif	}void paint(Node *u, Node *fa = NULL, int p = proCnt) {	if (u->belong) p = u->belong;	else u->belong = p;	for (Edge *e = u->firstEdge; e; e = e->next) {		if (e->v != fa) paint(e->v, u, p);	}}int main() {	int n;	scanf("%d %d", &n, &b);	if (b > n) {		puts("0");		return 0;	}	for (int i = 1; i <= n; i++) N[i].id = i;	for (int i = 1; i < n; i++) {		int u, v;		scanf("%d %d", &u, &v);		addEdge(u, v);	}	dfs(&N[1]);	if (!proCnt) cap[++proCnt] = 1;	paint(&N[1]);	printf("%dn", proCnt);	for (int i = 1; i <= n; i++) printf("%d%c", N[i].belong, i == n ? 'n' : ' ');	for (int i = 1; i <= proCnt; i++) printf("%d%c", cap[i], i == proCnt ? 'n' : ' ');	return 0;}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!