[UVA-1292-Strategic] game

链接

\(\text{UVA - 1292 Strategic game}\)

题意

  \(\text{Bob}\)在玩一款策略游戏,它需要保卫一个城市,很多道路将城市连起来,整体看起来像一棵树,\(\text{Bob}\)希望放置尽可能少的士兵到一些城市,包围连接这个城市的道路,士兵只能放在城市上即树的节点上,他可以保护与这个节点相邻的边。

  输入格式:多组测试样例,每个测试样例的第一行一个整数\(n\),表示城市个数,之后\(n\)行每行输入一个城市的信息x:(number) a1,a2...,表示与\(x\)城市直接连接的城市有\(number\)个,分别为\(a_1,a_2,...,a_{number}\)

  数据范围:\(0\leq n\leq 1500\).

  输出格式:输出一行,表示所需要放置的士兵的最小数量。

分析

  这是一个比较简单的树形\(dp\)

  对于一棵树的\(x\)节点来说,如果它不放士兵的话,那么它的每一个子节点\(y_i\)都需要放士兵,如果它放士兵的话,那么它的任意一个子节点\(y_i\),可能放士兵也可以不妨士兵。所以我们就得到了动态转移方程: \[\begin{cases}f[u][1]+=\min(f[v][0],f[v][1])\\f[u][0]+=f[v][1] \end{cases}v\in Son(u)\]

  \(f[i][1]\)表示在以\(i\)为根的子树中,如果\(i\)节点放士兵,所需要放置的最小士兵数量,\(f[i][0]\)表示在以\(i\)为根的子树中,如果\(i\)节点不放士兵,所需要放置的最小士兵数量;并且开始的时候,\(f[i][1]=1,f[i][0]=0\).

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <ostream>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <vector>

#define INF 0x7f7f7f7f
#define MAXN 1505
#define N 200005
#define P 2
//#define MOD 99991
#define MOD(a, b) a >= b ? a % b + b : a

typedef long long ll;

namespace fastIO {
//#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1<<22, stdin),
// p1 == p2) ? EOF : *p1++) char buf[(1 << 22)], *p1 = buf, *p2 = buf;
inline int read() {
char c = getchar();
int x = 0, f = 1;
while (c < '0' || c > '9') {
if (c == '-')
f = -1;
c = getchar();
}
while (c >= '0' && c <= '9')
x = x * 10 + c - '0', c = getchar();
return x * f;
}
} // namespace fastIO

using namespace fastIO;
using namespace std;

int cnt, n, vis[MAXN], f[MAXN][2];
char a, b, c;
vector<int> vec[MAXN];

void dfs(int u) {
f[u][1] = 1;
for (int i = 0; i < vec[u].size(); i++) {
int v = vec[u][i];
dfs(v);
f[u][1] += min(f[v][0], f[v][1]);
f[u][0] += f[v][1];
}
}

int main() {
//freopen("test.in", "r", stdin);
//freopen("test.out", "w", stdout);
int u, v;
while (cin >> n) {
memset(f, 0, sizeof(f));
memset(vis, 0, sizeof(vis));
for (int i = 0; i < n; i++)
vec[i].clear();

for (int k = 1; k <= n; k++) {
scanf("%d%c%c%d%c", &u, &a, &b, &cnt, &c);
//cout << u << " " << a << " " << b << " " << cnt << endl;
for (int i = 1; i <= cnt; i++) {
scanf("%d", &v);
//cout << v << endl;
vec[u].push_back(v);
vis[v] = 1;
}
}
int root;
for (int i = 0; i < n; i++)
if(!vis[i]){
root = i;
break;
}
dfs(root);
//cout << "\t" << 1 << endl;
cout << min(f[root][0], f[root][1]) << endl;
}
}