luogu3942 将军令 贪心

题目大意:给你一个地图(树),共有1~n个驿站(点),编号分别为1~n,告诉你第ui个驿站与第vi个驿站有一条长度为1的路(边),每个小队(可以放在任意驿站上)最多有k的覆盖长度,问最多要放置多少个小队才能把整张图全部覆盖?

把一个驿站当作市中心(树根),显然离市中心越偏远(深度越深)的驿站就越难被控制,所以我们优先考虑深度最深的节点。用来控制深度最深的节点v的小队应当布置在能控制到v且离v最远的节点u上,这样顺带着控制到的节点是最多的。所以具体操作为:将节点按照深度从大到小排序,判断是否覆盖过,如果没覆盖过,找其k级父亲并覆盖其周围距离不超过k的所有节点。这种方法没有后效性,因为选了一个节点不会导致其它节点不能选。

#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include <cstdarg>
using namespace std;

const int MAX_NODE = 100010;
int K;

void _printf(const char *format, ...)
{
#ifdef _DEBUG
	//va_list(args);
	//va_start(args, format);
	//vprintf(format, args);
	//va_end(args);
#endif
}

struct Node
{
	int Id;
	int Depth;
	Node *Fa;
	vector<Node*> Next;
	bool Ctrled;
}_nodes[MAX_NODE], *Root, *Order[MAX_NODE];
int TotNode;

void AddEdge(int uId, int vId)
{
	Node *u = _nodes + uId, *v = _nodes + vId;
	u->Id = uId, v->Id = vId;
	u->Next.push_back(v);
	v->Next.push_back(u);
}

void Read()
{
	int t, u, v;
	scanf("%d%d%d", &TotNode, &K, &t);
	for (int i = 1; i <= TotNode - 1; i++)
	{
		scanf("%d%d", &u, &v);
		AddEdge(u, v);
	}
}

void Init_Dfs(Node *cur, Node *fa, int depth)
{
	cur->Depth = depth;
	cur->Fa = fa;
	_printf("%d->%d depth %d\n", fa?fa->Id:0, cur->Id, cur->Depth);
	int len = cur->Next.size();
	for (int i = 0; i < len; i++)
		if (cur->Next[i] != fa)
			Init_Dfs(cur->Next[i], cur, depth + 1);
}

void SetDepth()
{
	Root = _nodes + 1;
	Init_Dfs(Root, NULL, 1);
}

bool Cmp_Depth(Node *a, Node *b)
{
	return a->Depth > b->Depth;
}

void SetOrder()
{
	for (int i = 1; i <= TotNode; i++)
		Order[i] = _nodes + i;
	sort(Order + 1, Order + TotNode + 1, Cmp_Depth);
}

void SetCtrl_Dfs(Node *fa, Node *cur, int k)
{
	_printf("ctrled %d\n", cur->Id);
	cur->Ctrled = true;
	int len = cur->Next.size();
	if (k < K)
		for (int i = 0; i < len; i++)
			if (cur->Next[i] != fa)
				SetCtrl_Dfs(cur, cur->Next[i], k + 1);
}

int SetCtrl()
{
	int ans = 0;
	for (int i = 1; i <= TotNode; i++)
	{
		Node *cur = Order[i];
		if (!cur->Ctrled)
		{
			_printf("deepest %d ", cur->Id);
			ans++;
			for (int j = 1; j <= K && cur->Fa; j++)
				cur = cur->Fa;
			_printf("lighted %d\n", cur->Id);
			SetCtrl_Dfs(NULL, cur, 0);
		}
	}
	return ans;
}

int main()
{
	Read();
	SetDepth();
	SetOrder();
	printf("%d\n", SetCtrl());
	return 0;
}

  

猜你喜欢

转载自www.cnblogs.com/headboy2002/p/8996205.html