• 洛谷2016


    题目描述

    Bob喜欢玩电脑游戏,特别是战略游戏。但是他经常无法找到快速玩过游戏的办法。现在他有个问题。

    他要建立一个古城堡,城堡中的路形成一棵树。他要在这棵树的结点上放置最少数目的士兵,使得这些士兵能了望到所有的路。

    注意,某个士兵在一个结点上时,与该结点相连的所有边将都可以被了望到。

    请你编一程序,给定一树,帮Bob计算出他需要放置最少的士兵.

    输入输出格式

    输入格式:

    第一行 N,表示树中结点的数目。

    第二行至第N+1行,每行描述每个结点信息,依次为:该结点标号i,k(后面有k条边与结点I相连)。

    接下来k个数,分别是每条边的另一个结点标号r1,r2,...,rk。

    对于一个n(0<n<=1500)个结点的树,结点标号在0到n-1之间,在输入数据中每条边只出现一次。

    输出格式:

    输出文件仅包含一个数,为所求的最少的士兵数目。

    ----------------------------------------------------------------------------------------------------------------------------------------------------------

    简单的树型动归

    f[u][1]=sum(f[son[u]][0])

    f[u][1]=1+sum(min(f[son[u]][0],f[son[u]][1]));

    答案就是:min(f[root][0],f[root][1])

    ----------------------------------------------------------------------------------------------------------------------------------------------------------

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=1505;
     4 struct edge
     5 {
     6     int u,v,nxt;
     7 }e[maxn<<1];
     8 int head[maxn],js;
     9 int n;
    10 int du[maxn];
    11 void addage(int u,int v)
    12 {
    13     e[++js].u=u;e[js].v=v;
    14     e[js].nxt=head[u];head[u]=js;
    15 }
    16 int f[maxn][2];
    17 void dfs(int u,int fa)
    18 {
    19     for(int i=head[u];i;i=e[i].nxt)
    20     {
    21         int v=e[i].v;
    22         if(v!=fa)
    23         {
    24             du[u]++;
    25             dfs(v,u);
    26         }
    27     }
    28 }
    29 void dp(int u,int fa)
    30 {
    31     if(du[u]==0)
    32     {
    33         f[u][0]=0;
    34         f[u][1]=1;
    35         return ;
    36     }
    37     f[u][1]=1;
    38     for(int i=head[u];i;i=e[i].nxt)
    39     {
    40         int v=e[i].v;
    41         if(v!=fa)
    42         {
    43             dp(v,u);
    44             f[u][0]+=f[v][1];
    45             f[u][1]+=min(f[v][0],f[v][1]);
    46         }
    47     }
    48 }
    49 int main()
    50 {
    51     scanf("%d",&n);
    52     for(int u,nm,i=0;i<n;++i)
    53     {
    54         scanf("%d%d",&u,&nm);
    55         for(int v,j=0;j<nm;++j)
    56         {
    57             scanf("%d",&v);
    58             addage(u,v);addage(v,u);
    59         }
    60     }
    61  //   memset(f,0x3fffffff,sizeof(f));
    62     dfs(0,-1);
    63     dp(0,-1);
    64     printf("%d",min(f[0][0],f[0][1]));
    65     return 0;
    66 }
    View Code
  • 相关阅读:
    归并排序(Merge Sort)
    AtCoder AGC035D Add and Remove (状压DP)
    AtCoder AGC034D Manhattan Max Matching (费用流)
    AtCoder AGC033F Adding Edges (图论)
    AtCoder AGC031F Walk on Graph (图论、数论)
    AtCoder AGC031E Snuke the Phantom Thief (费用流)
    AtCoder AGC029F Construction of a Tree (二分图匹配)
    AtCoder AGC029E Wandering TKHS
    AtCoder AGC039F Min Product Sum (容斥原理、组合计数、DP)
    AtCoder AGC035E Develop (DP、图论、计数)
  • 原文地址:https://www.cnblogs.com/gryzy/p/10143502.html
Copyright © 2020-2023  润新知