UVA1218 完美的服务 Perfect Service TJ

题目链接

补充

样例输入

6
1 3
2 3
3 4
4 5
4 6
0
2
1 2
-1

样例输出

2
1

思路

题目描述了一个树形结构,我们考虑使用树形 (DP) ,由于多了一个限制条件:一个客户端只有一个服务器。
那么我们设置三种状态:
(dp[u][0]) 表示当前节点 (u) 为服务器,孩子是否为服务器均可,
(dp[u][1]) 表示当前节点 (u) 为客户端, (u) 的父亲为服务器, (u) 的儿子均为客户端,
(dp[u][2]) 表示当前节点 (u) 为客户端, (u) 的父亲为客户端, (u) 的其中一个儿子为服务器。

第一个比较容易得到 (dp[u][0] = sum dp[v][1] + 1.)
第二个比较容易得到 (dp[u][1] = sum dp[v][2].)

下面我们分析第三个,容易得到 (dp[u][2] = min (dp[u][2] ,dp[V][0] + sum dp[v][2]).(V != v))
但是时间复杂度过于太高,那么我们考虑进行优化:
可以发现,(sum dp[v][2] = dp[u][1].) ,那么 (sum dp[v][2] + dp[V][0] = dp[u][1] - dp[V][2] + dp[V][0].)
可得状态转移方程: (dp[u][2] = min (dp[u][2] ,dp[u][1] - dp[V][2] + dp[V][0]).)

易错:初始化。

代码

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
using namespace std;
const int MAXN = 1e4 + 10;
struct node {
	int next ,to;
}edge[MAXN << 1];
int head[MAXN] ,cnt = 0;
void add (int from ,int to) {
	edge[++ cnt].next = head[from];
	head[from] = cnt;
	edge[cnt].to = to;
	return ;
}
int n ,dp[MAXN][3] ,rt;
void dfs (int u ,int fa) {
	dp[u][0] = 1 ,dp[u][1] = 0;
	dp[u][2] = 10010;
	for (int q = head[u];~ q;q = edge[q].next) {
		int v = edge[q].to;
		if (v == fa) continue;
		dfs (v ,u);
		dp[u][0] += min (dp[v][0] ,dp[v][1]);
		dp[u][1] += dp[v][2];
	}
	for (int q = head[u];~ q;q = edge[q].next) {
		int v = edge[q].to;
		if (v == fa) continue;
		dp[u][2] = min (dp[u][2] ,dp[u][1] - dp[v][2] + dp[v][0]);
	}
	return ;
}
void solve () {
	rt = 1;
	dfs (rt ,0);
	printf ("%d
",min (dp[rt][2] ,dp[rt][0]));
	return ;
}
int main () {
	int cmp ,from ,to;
	while (scanf ("%d",&n)) {
		memset (head ,-1 ,sizeof (head));
		cnt = 0;
		for (int q = 1;q < n;++ q) {
			scanf ("%d%d",&from ,&to);
			add (from ,to) ,add (to ,from);
		}
		solve ();
		scanf ("%d",&cmp);
		if (cmp == -1) break;
	}
	return 0;
}

cb
原文地址:https://www.cnblogs.com/tuscjaf/p/13894231.html