题目
WOJ#2532 战略游戏
洛谷P2016 战略游戏
这道题主要是看边的情况。
题目描述
Bob喜欢玩电脑游戏,特别是战略游戏。但是他经常无法找到快速玩过游戏的办法。现在他有个问题。
他要建立一个古城堡,城堡中的路形成一棵树。他要在这棵树的结点上放置最少数目的士兵,使得这些士兵能瞭望到所有的路。
注意:某个士兵在一个结点上时,与该结点相连的所有边将都可以被瞭望到。
请你编一个程序,给定一棵树,帮Bob计算出他需要放置最少的士兵数。
输入格式
第一行 N,表示树中结点的数目。
第二行至第N+1行,每行描述每个结点信息,依次为:该结点标号i,k(后面有k条边与结点I相连)。
接下来k个数,分别是每条边的另一个结点标号r1,r2,…,rk。
对于一个n(0<n<=1500)个结点的树,结点标号在0到n-1之间,在输入数据中每条边只出现一次。
输出格式
输出文件仅包含一个数,为所求的最少的士兵数目。
样例
- 样例输入
4
0 1 1
1 2 2 3
2 0
3 0 - 样例输出
1
题意
在一棵树上取若干个点,使得所有边都被连结。求点的个数的最小值。
思路
对于这类最值问题,应当用动态规划求解。
设
s
s
s是树的根,则设
f
[
s
]
f[s]
f[s]表示求以
s
s
s为根的子树上需要安放的最少士兵数量。我们希望用
s
s
s的儿子的对应信息来推出
f
[
s
]
f[s]
f[s]:
s
s
s有放和不放两种可能。当
s
s
s节点放时,它的子节点放和不放都可以;当
s
s
s节点不放时,它的子节点必须放。所以需要加维来表示树的根结点是否选取,才能从子树推算出父亲的最大值。
设 f [ i , 1 ] f[i,1] f[i,1]表示 i i i点放士兵时,以 i i i为根的子树需要的最少士兵数目; f [ i , 0 ] f[i,0] f[i,0]表示 i i i点不放士兵时,以 i i i为根的子树需要的最少士兵数目。
- 当点
i
i
i不放时,则它的所有儿子都必须放;
f [ i ] [ 0 ] = ∑ f [ j ] [ 1 ] f[i][0]=∑f[j][1] f[i][0]=∑f[j][1];其中 j j j为 i i i的儿子。 - 当点
i
i
i放时,则它的所有儿子放与不放无所谓,但应该取两种情况的最小值;
f [ i , 1 ] = ∑ m i n ( f [ j ] [ 1 ] , f [ j ] [ 0 ] ) f[i,1]=∑min(f[j][1],f[j][0]) f[i,1]=∑min(f[j][1],f[j][0]);其中 j j j为 i i i的儿子
初始条件:
f
[
i
]
[
0
]
=
0
,
f
[
i
,
1
]
=
1
f[i][0]=0,f[i,1]=1
f[i][0]=0,f[i,1]=1;
a
n
s
=
m
i
n
f
[
s
]
[
0
]
,
f
[
s
]
[
1
]
ans=min{f[s][0],f[s][1]}
ans=minf[s][0],f[s][1]。
代码
#include<iostream>
#include<cstdio>
#include<cctype>
using namespace std;
const int maxn=1510;
int n,s,cnt=2,ans=0;
int first[maxn],f[maxn][2];
struct edge {int u,v,w,nxt;};
edge e[maxn<<1];
inline int read()
{
int x=0;bool f=0;char c=getchar();
while(!isdigit(c)) {f|=c=='-';c=getchar();}
while(isdigit(c)) {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
return f?-x:x;
}
inline void add(int u,int v)
{
e[cnt].u=u;e[cnt].v=v;
e[cnt].nxt=first[u];first[u]=cnt++;
}
inline void dfs(int x,int fa)
{
f[x][0]=0,f[x][1]=1;
for(int i=first[x];i;i=e[i].nxt)
{
int y=e[i].v;
if(y==fa) continue;
dfs(y,x);
f[x][1]+=min(f[y][0],f[y][1]);
f[x][0]+=f[y][1];
}
}
int main()
{
n=read();
for(int i=1;i<=n;i++)
{
int idx=read(),k=read();
for(int j=1;j<=k;j++)
{
int r=read();
add(idx,r);
add(r,idx);
}
}
s=1;
dfs(0,-1);
ans=min(f[0][0],f[0][1]);
cout<<ans;
return 0;
}