UVA1218
定义:
S
o
n
[
i
]
Son[i]
Son[i]为第
i
i
i个节点的子节点集
d
p
[
i
]
dp[i]
dp[i]为以
i
i
i为根节点的最少服务器需求量
- d p [ i ] [ 0 ] dp[i][0] dp[i][0]为将第 i i i个节点作为服务器的时的情况,即它的子节点既可以是服务器,又可以是客户端。
- d p [ i ] [ 1 ] dp[i][1] dp[i][1]为第 i i i个节点为客户端且它的父节点为服务器的情况,即它的子节点只能是客户端。(一个客户端只能且必须能和一个服务器直接相连)
- d p [ i ] [ 2 ] dp[i][2] dp[i][2]为第 i i i个节点为客户端且它的父节点也为客户端的情况,即i有且只有一个子节点是服务器。
转移方程:
V
V
V为
i
i
i的子节点集合
- d p [ i ] [ 0 ] = ( ∑ v ∈ V m i n ( d p [ v ] [ 0 ] , d p [ v ] [ 1 ] ) ) + 1 dp[i][0]=(\sum\limits_{v\in V}{min(dp[v][0],dp[v][1])})+1 dp[i][0]=(v∈V∑min(dp[v][0],dp[v][1]))+1
- d p [ i ] [ 1 ] = ∑ v ∈ V d p [ v ] [ 2 ] dp[i][1]=\sum\limits_{v\in V}{dp[v][2]} dp[i][1]=v∈V∑dp[v][2]
-
d
p
[
i
]
[
2
]
=
m
i
n
(
d
p
[
v
k
]
[
0
]
+
∑
v
∈
V
−
v
k
d
p
[
v
]
[
2
]
)
=
m
i
n
(
d
p
[
v
k
]
[
0
]
+
d
p
[
i
]
[
1
]
−
d
p
[
v
k
]
[
2
]
dp[i][2]=min(dp[v_k][0]+\sum\limits_{v\in {V-v_k}}{dp[v][2]})=min(dp[v_k][0]+dp[i][1]-dp[v_k][2]
dp[i][2]=min(dp[vk][0]+v∈V−vk∑dp[v][2])=min(dp[vk][0]+dp[i][1]−dp[vk][2]
即枚举 i i i的每一个子节点作为服务器的情况。
AC代码:
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>
#include<map>
using namespace std;
int N, Status;
vector<int> Son[10001];
int dp[10001][3];
void Clear() {
for (int i = 1; i <= N; ++i) {
Son[i].clear();
}
}
void Input() {
cin >> N;
Clear();
for (int i = 1; i < N; ++i) {
int x, y;
cin >> x >> y;
Son[x].push_back(y);
Son[y].push_back(x);
}
}
void DP(int Root,int Father) {
dp[Root][0] = 1;
dp[Root][1] = 0;
dp[Root][2] = 10000;//inf
for (auto SonIt = Son[Root].cbegin(); SonIt != Son[Root].cend(); ++SonIt) {
if (*SonIt == Father) {
continue;
}
DP(*SonIt, Root);
dp[Root][0] += min(dp[*SonIt][0], dp[*SonIt][1]);
dp[Root][1] += dp[*SonIt][2];
}
for (auto SonIt = Son[Root].cbegin(); SonIt != Son[Root].cend(); ++SonIt) {
if (*SonIt == Father) {
continue;
}
dp[Root][2] = min(dp[Root][2], dp[Root][1] - dp[*SonIt][2] + dp[*SonIt][0]);
}
}
int main() {
while (true) {
Input();
DP(1, -1);
cout <<min(dp[1][0],dp[1][2]) << endl;
cin >> Status;
if (Status == -1) {
break;
}
}
return 0;
}