树形DP专辑--POJ 1463 Strategic game

Strategic game
Time Limit: 2000MS   Memory Limit: 10000K
Total Submissions: 5737   Accepted: 2615

Description

Bob enjoys playing computer games, especially strategic games, but sometimes he cannot find the solution fast enough and then he is very sad. Now he has the following problem. He must defend a medieval city, the roads of which form a tree. He has to put the minimum number of soldiers on the nodes so that they can observe all the edges. Can you help him?

Your program should find the minimum number of soldiers that Bob has to put for a given tree.

For example for the tree:
树形DP专辑--POJ 1463 Strategic game_第1张图片
the solution is one soldier ( at the node 1).

Input

The input contains several data sets in text format. Each data set represents a tree with the following description:

  • 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

The output should be printed on the standard output. For each given input data set, print one integer number in a single line that gives the result (the minimum number of soldiers). An example is given in the following:

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

选尽量少的点覆盖与其关联的边;

/********************************************************************
* 题目:Strategic game
* source:POJ
* 分类:树形DP专辑
* 题意:题意:给一个无根树,选一些点,选了1个点,
* 与该点关联的边都会被覆盖,问要覆盖完所有的边,至少选多少个点
* 分析:dp[u][0],要覆盖u子树的所有边,且u不选的最小花费
* dp[u][1],要覆盖u子树的所有边,且u选的最小花费;
* dp[u][0]:因为u不选了,而u和儿子v的连线总是要覆盖的,那只好选所有的儿子,
* 才能覆盖这些边
* dp[u][0] = sigma(dp[v][1]);
* dp[u][1]:因为u选了,那么u和儿子的边,都被覆盖了,这样儿子选不选问题都行,
* 最后都可以覆盖所有边,那么就当然选花费小的
* dp[u][1]=sigma(min(dp[v][0],dp[v][1]));
* 边界:对于叶子,dp[leaf][0]=0;dp[leaf][1] = 1;
* author:crazy_石头
* 吐槽:跟着G-rated大牛的blog刷不动啊~~略难,只会划水的狗无语了。。。。。
***************************************************************************/
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int maxn=1500+5;

struct Edge
{
    int to;
    int next;
}edge[maxn<<2];

int dp[maxn][2];
int head[maxn];
bool vis[maxn];

int cnt;

int n;
inline int max(int a,int b)
{
    return a>b?a:b;
}

inline int min(int a,int b)
{
    return a<b?a:b;
}

inline void addedge(int u,int v)
{
     edge[cnt].to=v;
     edge[cnt].next=head[u];
     head[u]=cnt++;
}

inline void makemap(int from,int to)
{
     addedge(from,to);
     addedge(to,from);
}


inline void DFS(int u)
{
     vis[u]=1;
     dp[u][0]=0;
     dp[u][1]=1;//边界条件;

     for(int i=head[u];~i;i=edge[i].next)
     {
        int v=edge[i].to;
        if(!vis[v])//若该点未访问过,访问该点;
        {
             DFS(v);
             dp[u][0]=dp[u][0]+dp[v][1];//更新此时的结果;
            dp[u][1]=dp[u][1]+min(dp[v][0],dp[v][1]);
         }
     }
}

inline void init()
{
     cnt=0;
     memset(head,-1,sizeof(head));
     memset(vis,0,sizeof(vis));
}

int main()
{
     int u,v,t,m;
     while(scanf("%d",&n)!=EOF)
     {
         init();
         memset(dp,0,sizeof(dp));
         while(n--)
         {
             scanf("%d:(%d)",&u,&t);
             for(int i=0;i<t;i++)
             {
                 scanf("%d",&v);
                 makemap(u,v);
             }
         }
         DFS(u);
         printf("%d\n",min(dp[u][0],dp[u][1]));
     }
     return 0;
}


 

你可能感兴趣的:(树形DP专辑--POJ 1463 Strategic game)