zoukankan      html  css  js  c++  java
  • AOJ 911 组队分配 【树形DP】

    ---恢复内容开始---

    题面:

    有一个n个节点n-1条边组成的树。
    每个点看成一个人,连接u和v的边看成是“中意关系”,即u和v两个人都想和对方组队。每个人希望组队的对象有可能有多个。
    一支队伍由且仅由两个人组成,并且如果u和v组队了,那么u、v将不能和其他人再组成一支队。
    现在问你,这n个人最多能组成多少支队伍。(允许某些人组不了队)

    Input

    第一行输入一个整数n,m(1<=n<=200000)
    接下来n-1行,每行两个整数u,v,表示u和v两个人都想和对方组队。
    数据保证是一个合法的树。

    Output

    输出一个整数,表示最多能组成多少支队伍。

    Input

    5

    1 2

    1 3

    2 4

    4 5

    Output

    2

    大致思路:

    首先看到题面,其实很容易想到是一道树形DP。但树上的关系在比赛时间里没有想明白,导致没有做出来。

    对于每一个节点,都有取或者不取两个可能。分别用dp[k][1]和dp[k][0]来表示

    然后就是节点之间的关系了,对于每一个节点来说,若不取这个点,则肯定是对于每一个子节点的取或者不取求一个max

    也就是 dp[k][0]+=max(dp[ v ] [ 1 ] , dp [ v ] [ 0 ] )  v是k的子节点

    但对于dp[k][1]就有点麻烦了,因为如果要让dp[k][1]成立,则必然有至少加上一个子节点不取的情况。

     1 void tree_dp(int k,int last)
     2 {
     3     int v;
     4     bool flag=false;
     5     for(int i=0;i<g[k].size();++i){
     6         v=g[k][i];
     7         if(v==last)
     8             continue;
     9         tree_dp(v,k);
    10         if(dp[v][1]>dp[v][0])//对每一个dp[v]进行选择,如果取的情况值较大,就直接加到dp[v][0]上
    11 dp[k][0]+=dp[v][1]; 12 else{//否则就表示第k个节点是可以取到的,同时标记flag。 13 flag=true; 14 dp[k][0]+=dp[v][0];//这里依然加给dp[v][0]是因为在最后会加给dp[k][1],而且第k个点最多只能取一次
    15 } 16 } 17 dp[k][1]=dp[k][0];//如果第k个取不到,直接赋值给dp[k][1],对下一层决策无影响 18 if(flag) 19 dp[k][1]++; 20 }

    代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=2e5+7;
     4 int dp[maxn][2],ans=0;
     5 vector<int> g[maxn];
     6 void tree_dp(int k,int last)
     7 {
     8     int v;
     9     bool flag=false;
    10     for(int i=0;i<g[k].size();++i){
    11         v=g[k][i];
    12         if(v==last)
    13             continue;
    14         tree_dp(v,k);
    15         if(dp[v][1]>dp[v][0])
    16             dp[k][0]+=dp[v][1];
    17         else{
    18             flag=true;
    19             dp[k][0]+=dp[v][0];
    20         }
    21     }
    22     dp[k][1]=dp[k][0];
    23     if(flag)
    24         dp[k][1]++;
    25 }
    26 int main()
    27 {
    28     ios::sync_with_stdio(false);
    29     //freopen("in.txt","r",stdin);
    30     //freopen("ou1.txt","w",stdout);
    31     memset(dp,0,sizeof(dp));
    32     int n,u,v;
    33     cin>>n;
    34     for(int i=0;i<n-1;++i){
    35         cin>>u>>v;
    36         g[u].push_back(v);
    37         g[v].push_back(u);
    38     }
    39     tree_dp(1,1);
    40     //for(int i=1;i<=n;++i)
    41      //   cout<<i<<" "<<dp[i][1]<<" "<<dp[i][0]<<endl;
    42     ans=max(dp[1][0],dp[1][1]);
    43     cout<<ans<<endl;
    44     return 0;
    45 }

    ---恢复内容结束---

  • 相关阅读:
    gifplayer-可控制GIF动画图片播放和暂停jQuery插件
    ERROR 2003 (HY000): Can't connect to MySQL server on
    linux下重启nginx
    查看MySQL的当前存储引擎
    MySQL查看表占用空间大小
    使用Sequel Pro通过ssh远程连接MySQL出错:The SSH Tunnel has unexpectedly closed
    textview 内容从头开始显示
    SQL优化
    运营平台框架整理(内部用)
    线程的取消和关闭
  • 原文地址:https://www.cnblogs.com/SCaryon/p/7482214.html
Copyright © 2011-2022 走看看