Solution to a problem P3155 [[CQOI2009] stained leaves]

First unscrupulous propaganda about the blog \ (wwwwww \)
list of articles - nuclear fusion reactor core - Luo Gubo off


Knowledge Point: tree \ (DP \) , \ (the DFS \)

  • Analysis of the meaning of problems:

    It is easy to prove, free to choose not to point a leaf node is the root
    does not have any effect on the answer

    • Proof: the title,
      the coloring scheme should ensure that the root to the simple path to each leaf
      contains at least one colored nodes (even if it is the leaf itself)
      coloring scheme leaf nodes
      only above it the first colored node related
      result , proved.

    From the above, assuming a non-randomly selected leaf node as the root node:
    and, setting \ (F [I] [J] \) , for the first \ (I \) points, which is dyed \ (J \) color, the required price

    • Can be learned,
      if one node needs to be dyed \ (x \) color,
      and his father node has been dyed \ (x \) color
      is, he does not need to be dyed,
      you can inherit his father's colors

    • Then, for a certain node,
      which is dyed \ (X \) the cost of color,

      1. Can be directly inherited his father were stained \ (x \) the cost of color
      2. May be maintained non-father \ (X \) color,
        and a single node dyed \ (X \) color

    State transition equation is obtained:

    f[u][0]+=min(f[v][0]-1,f[v][1]); //u表示v的父亲节点   
    f[u][1]+=min(f[v][1]-1,f[v][0]);

    Said node will be dyed a color \ (j \) price,
    namely: for all its child nodes dyed colors \ (j \) cost and.


  • Algorithm:

    This enables the tree \ (the DP \) :

    • Initialization:
      \ (F [I] [1] = 1 \, \ F [I] [0] = 1 \) ,
      representative of each point, the cost of a certain color are dyed \ (1 \)

      In particular, for leaf nodes, \ (F [I] [\ (! C [I]) \] = INF \) , \ ((\ C [I] \) is a leaf node should become the color \ () \) ,
      represents a leaf node \ (i \) should not be dyed other colors,
      so set a great price, guaranteed not to be used to update other nodes

    After that, free to choose a non-leaf node, as root, start \ (DFS \)

    1. When a leaf node is reached,
      direct \ (return; \) (the cost of a leaf node does not need to be updated)
    2. Otherwise, the loop enumerates all non-father node ,
      to update their values
    3. When a node to be returned to the recursive,
      sub-nodes it has been updated,
      to update its value

    \ (The DFS \) is completed, all the obtained \ (F [] [] \) values.
    Since there root \ (0 \) where two colors
    so that the two root value \ (F [root] [0] \) and \ (f [root] [1 ] \) in, takes a minimum value
    i.e. the required answers.


The Code (No need to comment so much of it) :

#include<cstdio>
#include<queue>
#include<ctype.h>
#define int long long
#define min(a,b) a<b?a:b
//======================================================
const int MARX = 1e4+10;
const int INF = 2147483647;//极大值 
struct edge 
{
    int u,v,ne;
}e[2*MARX];
int m,n,c[MARX];//输入数据 
int root,num,head[MARX]; //建树 
int f[MARX][2]; // f[i][j]表示,第i个点,将其染成j颜色,所需要的代价
//======================================================
inline int read()
{
    int fl=1,w=0;char ch=getchar();
    while(!isdigit(ch) && ch!='-') ch=getchar();
    if(ch=='-') fl=-1;
    while(isdigit(ch)){w=w*10+ch-'0',ch=getchar();}
    return fl*w;
}
inline void add(int u,int v)
{
    e[++num].u=u,e[num].v=v;
    e[num].ne=head[u],head[u]=num;
}
void dfs(int u,int fa)
{
    if(u<=n) return ;//叶节点,直接return ; 
    for(int i=head[u],v=e[i].v;i;i=e[i].ne,v=e[i].v)//枚举所有非父节点 
      if(v!=fa)
      {
        dfs(v,u);
        f[u][0]+=min(f[v][0]-1,f[v][1]);//用子节点,更新当前点的各值 
        f[u][1]+=min(f[v][1]-1,f[v][0]);
      }
}
//======================================================
signed main()
{
    m=read(),n=read();
    root=n+1;//随意选择一个不为叶节点的节点 
    for(int i=1;i<=n;i++) c[i]=read();
    for(int i=1;i<=m-1;i++)
    {
      int u=read(),v=read();
      add(u,v),add(v,u);
    }
    for(int i=1;i<=m;i++)//初始化 
    {
      f[i][0]=f[i][1]=1;
      if(i<=n) f[i][(!c[i])]=INF;//叶节点特殊初始化 
    }
    dfs(root,root);
    printf("%lld",min(f[root][0],f[root][1]));//取较小的值 
}

Guess you like

Origin www.cnblogs.com/luckyblock/p/11456303.html