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
思路 |
和间接上司那道题很像,每个支点有两种状态,放个士兵或者不放士兵。 因此得到状态转移方程: dp[i][0]+=dp[i.son][1]; dp[rr][1]+=min(dp[i.son][0], dp[i.son][1]); |
源码 |
#include<stdio.h> #include<string.h> #include<vector> #include<iostream> using namespace std; int dp[1505][2]; vector<int>V[1505]; void dfs(int rr) { int longs=V[rr].size(), i, j; if(longs==0) { dp[rr][0]=0; dp[rr][1]=1; return ; } else { for(i=0; i<longs; i++) { dfs(V[rr][i]); dp[rr][0]=0; dp[rr][1]=1; for(j=0; j<longs; j++) { dp[rr][0]+=dp[V[rr][j]][1]; dp[rr][1]+=min(dp[V[rr][j]][0], dp[V[rr][j]][1]); } } } } int main() { int n, i, j, son[1505], sonnum, ff, root, ss; while(scanf("%d", &n)!=EOF) { memset(son, 0, sizeof(son)); memset(dp, 0, sizeof(dp)); for(i=0; i<n; i++) V[i].clear(); for(i=0; i<n; i++) { scanf("%d:(%d)", &ff, &sonnum); for(j=0; j<sonnum; j++) { scanf("%d", &ss); son[ss]=1; V[ff].push_back(ss); } } for(i=0; i<n; i++) if(!son[i]) { root=i; break; } dfs(root); printf("%d\n", min(dp[root][1], dp[root][0])); } } |