夹克老爷的愤怒

夹克老爷逢三抽一之后,由于采用了新师爷的策略,乡民们叫苦不堪,开始组织起来暴力抗租。

夹克老爷很愤怒,他决定派家丁常驻村中进行镇压。

诺德县 有N个村庄,编号0 至 N-1,这些村庄之间用N - 1条道路连接起来。

家丁都是经过系统训练的暴力机器,每名家丁可以被派驻在一个村庄,并镇压当前村庄以及距离该村庄不超过K段道路的村庄。

夹克老爷一贯奉行最小成本最大利润的原则,请问要实现对全部村庄的武力控制,夹克老爷需要派出最少多少名家丁?
 

Input

第1行:2个数N, K中间用空格分隔(1<= N <= 100000, 0 <= K <= N)。
之后N-1行:每行2个数S, E中间用空格分隔,表示编号为S的村庄同编号为E的村庄之间有道路相连。(0 <= S, E < N)。

Output

输出一个数说明要实现对全部村庄的武力控制,夹克老爷需要派出最少多少名家丁?

Input示例

4 1
0 1
0 2
0 3

Output示例

1

思路:

树形dp。遍历每一个节点的每一个子树,记录下最大子树深度和最小子树深度。

当最小子树深度小于等于-k时家丁加一。

#include <iostream>    
#include <vector>    
#include <string>    
using namespace std;  
  
const int INF = 0x3f3f3f3f;
const int MAXN = 1e5 + 5;
int result;
int n, k, s, e;
int dp[MAXN];
vector<int> edge[MAXN];

void dfs(int node, int fa)
{
	int minn = INF;
	int maxn = -INF;
	
	for (int i = 0; i < edge[node].size(); i++)
	{
		int peer = edge[node][i];
		if (peer != fa)
		{
			dfs(peer, node);
			minn = min(minn, dp[peer]);
			maxn = max(maxn, dp[peer]);
		}
	}

	if (minn <= -k)
	{
		result++;
		dp[node] = k;
	}
	else if (minn == INF)
	{
		dp[node] = -1;
	}
	else if (maxn + minn > 0)
	{
		dp[node] = maxn - 1;
	}
	else
	{
		dp[node] = minn - 1;
	}
}

int main()  
{  
	cin >> n >> k;
	for (int i = 0; i < n - 1; i++)
	{
		cin >> s >> e;
		edge[s].push_back(e);
		edge[e].push_back(s);
	}

	if (k == 0)
	{
		cout << n << endl;
		return 0;
	}

	dfs(0, -1);

	if (dp[0] < 0)
	{
		result++;
	}

	cout << result <<endl;

    return 0;  
}  

 

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页