标签:
Crawling in process... Crawling failed Time Limit:2000MS Memory Limit:10000KB 64bit IO Format:%I64d & %I64u
Description
Input
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
题目大意:给你一个树状结构,每一个节点都可以放置士兵,可以看守住与 该节点相邻的所有边,问你最少需要多少个节点。
思路分析:树的最小点覆盖问题,首先确定状态f[i[0]表示在根节点i上不放置士兵看守住这棵子树需要的最少士兵,f[i][0]
则代表根结点i上不放置士兵看守住所需要的最少士兵,状态转移方程f[i][1]+=min(f[j][1],f[j][0]),f[i][0]+=f[j][1]
初始化f[i][[1]=1,f[i][0]=0;
代码:
/*树的最小点覆盖 */ #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn=1500+10; int fat[maxn]; int dp[maxn][2]; bool vis[maxn];//标记 int n; void dfs(int x) { //cout<<x<<endl; vis[x]=true; dp[x][1]=1; dp[x][0]=0; for(int i=0;i<n;i++) { if(!vis[i]&&fat[i]==x) { dfs(i); dp[x][1]+=min(dp[i][0],dp[i][1]);//子节点可放可不放 dp[x][0]+=dp[i][1]; } } } int main() { int r,num; int a; int i; while(scanf("%d",&n)!=EOF) { // cout<<n<<endl; memset(fat,0,sizeof(fat)); memset(vis,false,sizeof(vis)); for(int k=0;k<n;k++) { scanf("%d:(%d)",&r,&num); //cout<<r<<" "<<num<<endl; for(int i=1;i<=num;i++) { scanf("%d",&a); fat[a]=r; // cout<<a<<endl; } } // for(int i=0;i<n;i++) //cout<<fat[i]<<endl; for(i=0;i<n;i++) { if(!fat[i]) { //cout<<i<<endl; dfs(i); cout<<min(dp[i][0],dp[i][1])<<endl; break; } } } return 0; }
标签:
原文地址:http://www.cnblogs.com/xuejianye/p/5662501.html