题目大意:给出一个树形图,结点放置士兵看守与这个结点相邻的路,问最少放置多少个士兵能把所有路看守住
输入:结点个数n(0<=n<=1500)
结点符号:(相邻路的个数) 相邻结点i ...//相邻路数不超过10,且每条路只出现一次
或
结点符号:(0)//没有相邻的路
输出:最少士兵个数
分析:树形动态规划dfs
状态:dp[i][0]表示i结点不放士兵所用的最少士兵数,dp[i][1]表示i结点放置士兵所用的最少士兵数
状态转移方程:dp[i][0]=sum{d[j][1]},j是与i有边的结点//i不放士兵,则与他相邻的结点一定放士兵
dp[i][1]=sum{min{dp[j][0],dp[j][1]}},j是与i有边的士兵//i放了士兵,则与他相邻的结点可放可不放
结果:min{dp[root][0],dp[root][1]}
初始化:dp[root][0]=0,dp[root][1]=1
代码:转载自http://blog.csdn.net/SelinaFelton/article/details/51872243
#include <stdio.h>
#include <iostream>
#include <vector>
#include <string.h>
using namespace std ;
#define MAX 1510
vector<vector<int>> tree(MAX) ;
int f[MAX] , n , dp[MAX][2];
void DFS(int root)
{
dp[root][0]=0;
dp[root][1]=1;
int len = tree[root].size();
for(int i = 0 ; i < len ; i ++)
{
DFS(tree[root][i]) ;
dp[root][1] += min(dp[tree[root][i]][1],dp[tree[root][i]][0]) ;
dp[root][0] += dp[tree[root][i]][1] ;
}
}
int main()
{
int edge , fa , son ;
while(scanf("%d",&n)!=EOF)
{
memset(f , -1 , sizeof(f)) ;
for(int i = 1 ; i <= n ; i ++)
{
scanf("%d:(%d)", &fa , &edge);
tree[fa].clear();
while(edge --)
{
scanf("%d",&son) ;
tree[fa].push_back(son) ;
f[son] = fa ;
}
}
int a = 1 ;
while(f[a]!= -1) a=f[a]; //找到树形图的根节点,即没有父亲的那个节点
DFS(a);
printf("%d\n" , min(dp[a][0],dp[a][1])) ;
}
return 0 ;
}