Time Limit: 2000MS | Memory Limit: 10000KB | 64bit IO Format: %I64d & %I64u |
Description
Your program should find the minimum number of soldiers that Bob has to put for a given tree.
For example for the tree:
the solution is one soldier ( at the node 1).
Input
- the number of nodes
- the description of each node in the following format
node_identifier:(number_of_roads) node_identifier1 node_identifier2 ... node_identifiernumber_of_roads
or
node_identifier:(0)
The node identifiers are integer numbers between 0 and n-1, for n nodes (0 < n <= 1500);the number_of_roads in each line of input will no more than 10. Every edge appears only once in the input data.
Output
Sample Input
4 0:(1) 1 1:(2) 2 3 2:(0) 3:(0) 5 3:(3) 1 4 2 1:(1) 0 2:(0) 0:(0) 4:(0)
Sample Output
1 2
Source
題意:有一棵樹,在一個節點上放一個戰士,相鄰的點也會受到保護,問最少需要多少戰士,纔可以使所有的點都得到保護,即求樹的最小點覆蓋~ 樹狀DP,和POJ 2342大同小異~
AC代碼:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define maxn 1500+5
int n,dp[maxn][2],fa[maxn],vis[maxn];
void dfs(int x)
{
vis[x] = 1;
for(int i = 0;i < n;i ++)
{
if(!vis[i] && fa[i] == x)
{
dfs(i);
dp[x][0] += dp[i][1];
dp[x][1] += min(dp[i][0], dp[i][1]);
}
}
return;
}
int main()
{
int from, to, root, m;
char c1, c2;
while(scanf("%d", &n) != EOF)
{
for(int i = 0;i < n;i ++)
fa[i] = -1;
memset(vis, 0, sizeof(vis));
for(int i = 0;i < n;i ++)
{
scanf("%d%c%c",&from,&c1,&c2);
scanf("%d", &m);
getchar();
while(m --)
{
scanf("%d",&to);
fa[to] = from;
}
}
for(int i = 0;i < n;i ++)
{
if(fa[i] == -1) root = i;
dp[i][0] = 0;
dp[i][1] = 1;
}
dfs(root);
printf("%d\n",min(dp[root][0], dp[root][1]));
}
return 0;
}