题目:战略游戏
思路:
可以知道,一个节点不用放哨兵,那么它的父节点和所有的子节点都必须放哨兵。
令
f[x][w]
f
[
x
]
[
w
]
表示第
x
x
个节点放哨兵的状态为所用的最少哨兵数量。其中,
bool w
b
o
o
l
w
为
0
0
代表没放哨兵,为代表放了哨兵。
转移方程:
f[x][1]=∑min(f[y][0],f[y][1]+1)
f
[
x
]
[
1
]
=
∑
m
i
n
(
f
[
y
]
[
0
]
,
f
[
y
]
[
1
]
+
1
)
f[x][0]=∑f[y][1]+1
f
[
x
]
[
0
]
=
∑
f
[
y
]
[
1
]
+
1
这里的
y
y
指所有的子节点。
代码:
#include<bits/stdc++.h>
using namespace std;
#define maxn 1500
int n;
vector<int> a[maxn+5];
int f[maxn+5][3];
void read(int& x) {
scanf("%d",&x);
}
int dfs(int x,int fa,int w) {
if(f[x][w]) return f[x][w];
if(w==0)
for(int i=0;i<a[x].size();i++) {
int y=a[x][i];
if(y==fa) continue;
f[x][w]+=dfs(y,x,1)+1;
}
else
for(int i=0;i<a[x].size();i++) {
int y=a[x][i];
if(y==fa) continue;
f[x][w]+=min(dfs(y,x,0),dfs(y,x,1)+1);
}
return f[x][w];
}
int main() {
read(n);
for(int i=1;i<=n;i++) {
int x,k;
read(x);read(k);
x++;
while(k--) {
int y;
read(y);
y++;
a[x].push_back(y);
a[y].push_back(x);
}
}
int ans=min(dfs(1,0,0),dfs(1,0,1)+1);
printf("%d",ans);
return 0;
}
1042

被折叠的 条评论
为什么被折叠?



