PKU Tour in Wonder Land 树型DP

PKU Tour in Wonder Land 树型DP

这道题题意是:
从根节点出发,每条边仅仅走一遍,每个节点仅仅走一遍,问遍历完整棵树然后回到根需要加多少条边。
这题的本质是在树的路径最小划分。可以使用树形DP
状态dp[pos][0]表示遍历完这颗子树并且链的一端在根节点最少需要添加边的数量
dp[pos][1]表示完遍历这颗子树需要添加最少的边的数量
然后下面状态转移就简单了
son[pos]=dp[i][1],i为父节点为pos的子树
num[pos]为以pos为根节点的子树数量
dp[pos][0]=min(son[pos]+dp[i][0]-dp[i][1]+num[pos]-1),i为以pos为根的子树
dp[pos][1]=min(son[pos]+dp[i][0]-dp[i][1]+dp[j][0]-dp[j][1]+num[pos]-2),i为以pos为根的子树
 1  # include  < stdio.h >
 2  # include  < string .h >
 3  # include  < stdlib.h >
 4  # define N  110000
 5  # define M  210000
 6  int  g[N],n,tmp[N];
 7  int  nxt[M],v[M],c = 0 ;
 8  int  dp[N][ 2 ];
 9  void  solve( int  pos, int  fa)
10  {
11       if (dp[pos][ 0 ] !=- 1 return ;
12       else
13      {
14           int   null = 0 ,p,total = 0 ,num = 0 ,min1 = 0xfffffff ,min2 = 0xfffffff ;
15           for (p = g[pos];p !=- 1 ;p = nxt[p])
16              if (v[p] != fa)
17             {
18                 null = 1 ;
19                solve(v[p],pos);
20                 if (dp[v[p]][ 0 ] - dp[v[p]][ 1 ] < min1)
21                {
22                  min2 = min1;
23                  min1 = dp[v[p]][ 0 ] - dp[v[p]][ 1 ];
24                }
25                 else   if (dp[v[p]][ 0 ] - dp[v[p]][ 1 ] < min2)
26                {
27                  min2 = dp[v[p]][ 0 ] - dp[v[p]][ 1 ];
28                }
29                total += dp[v[p]][ 1 ];
30                num ++ ;
31             }
32           if ( ! null )
33             dp[pos][ 0 ] = dp[pos][ 1 ] = 0 ;
34            else
35           {
36               dp[pos][ 0 ] = total + min1 + num - 1 ;
37                if (min2 != 0xfffffff )
38                 dp[pos][ 1 ] = total + min1 + min2 + num - 2 ;
39                if (dp[pos][ 0 ] < dp[pos][ 1 ] || dp[pos][ 1 ] ==- 1 )
40                  dp[pos][ 1 ] = dp[pos][ 0 ];
41           }  
42      }
43  }
44  int  main()
45  {
46       int  i;
47      scanf( " %d " , & n);
48      memset(g, - 1 , sizeof (g));
49      c = 0 ;
50       for (i = 1 ;i < n;i ++ )
51      {
52            int  a,b;
53           scanf( " %d%d " , & a, & b);
54           v[c] = b;
55           nxt[c] = g[a];
56           g[a] = c ++ ;
57           v[c] = a;
58           nxt[c] = g[b];
59           g[b] = c ++ ;
60      }
61      memset(dp, - 1 , sizeof (dp));
62      solve( 1 , 0 );
63      printf( " %d\n " ,dp[ 1 ][ 1 ] + 1 );
64       return   0 ;
65  }
66 


你可能感兴趣的:(PKU Tour in Wonder Land 树型DP)