zoukankan      html  css  js  c++  java
  • UVa 1220

    链接:

    https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3661

    题意:

    公司里有n(n≤200)个人形成一个树状结构,即除了老板之外每个员工都有唯一的直属上司。
    要求选尽量多的人,但不能同时选择一个人和他的直属上司。问:最多能选多少人,以及在人数最多的前提下方案是否唯一。

    分析:

    本题几乎就是树的最大独立集问题,不过多了一个要求:判断唯一性。
    一、设d(u,0)和f(u,0)表示以u为根的子树中,不选u点能得到的最大人数以及方案唯一性(f(u,0)=1表示唯一,0表示不唯一)。
    二、设d(u,1)和f(u,1)表示以u为根的子树中,选u点能得到的最大人数以及方案唯一性。相应地,状态转移方程也有两套。
    三、d(u,1)的计算:因为选了u,所以u的子结点都不能选,故d(u,1) = sum{d(v,0) | v是u的子结点}。当所有f(v,0)=1时f(u,1)=1。
    四、d(u,0)的计算:因为u没有选,所以每个子结点v可选可不选,即d(u,0) = sum{ max(d(v,0), d(v,1)) }。
    什么情况下方案是唯一的呢?首先,如果某个d(v,0)和d(v,1)相等,则不唯一;
    其次,如果max取到的那个值对应的f=0,方案也不唯一(如d(v,0) > d(v,1) 且f(v,0)=0,则f(u,0)=0)。

    代码:

     1 #include <cstdio>
     2 #include <map>
     3 #include <string>
     4 #include <vector>
     5 using namespace std;
     6 
     7 const int UP = 200 + 5;
     8 int cid, d[UP][2]; // d数组表示以f为根的子树中,选或不选f点能得到的最大人数
     9 bool u[UP][2]; // u数组表示以f为根的子树中,选或不选f点的方案唯一性
    10 map<string, int> M;
    11 vector<int> son[UP];
    12 
    13 int id(char* s){
    14     if(M.count(s)) return M[s];
    15     return M[s] = cid++;
    16 }
    17 
    18 int dp(int f, int p){
    19     d[f][p] = p;
    20     u[f][p] = true;
    21     for(int i = 0; i < son[f].size(); i++){
    22         int b = son[f][i];
    23         if(p == 1){
    24             d[f][1] += dp(b, 0);
    25             if(!u[b][0]) u[f][1] = false;
    26         }
    27         else{
    28             d[f][0] += max(dp(b, 0), dp(b, 1));
    29             if(d[b][0] == d[b][1]) u[f][0] = false;
    30             else if(d[b][0] > d[b][1] && !u[b][0]) u[f][0] = false;
    31             else if(d[b][1] > d[b][0] && !u[b][1]) u[f][0] = false;
    32         }
    33     }
    34     return d[f][p];
    35 }
    36 
    37 int main(){
    38     int n;
    39     char f[999], b[999];
    40     while(scanf("%d", &n) && n){
    41         cid = 0;  M.clear();
    42         for(int i = 0; i < n; i++) son[i].clear();
    43 
    44         scanf("%s", f);  id(f);
    45         for(int i = 1; i < n; i++){
    46             scanf("%s%s", b, f);
    47             son[id(f)].push_back(id(b));
    48         }
    49 
    50         printf("%d ", max(dp(0, 0), dp(0, 1)));
    51         bool ok = (d[0][0]>d[0][1]&&u[0][0]) || (d[0][1]>d[0][0]&&u[0][1]);
    52         printf("%s
    ", ok ? "Yes" : "No");
    53     }
    54     return 0;
    55 }
  • 相关阅读:
    JPA各种类型映射处理
    HTML URL编码
    C# 温故而知新:Stream篇(二)
    数据集
    C#可调用API接口来获取窗口句柄,代码如下:
    C# 温故而知新:Stream篇(三)
    SQL的主键和外键约束
    C# 温故而知新: 线程篇(三)
    C# 温故而知新:Stream篇(四)
    C# 温故而知新:Stream篇(—)
  • 原文地址:https://www.cnblogs.com/hkxy125/p/8627510.html
Copyright © 2011-2022 走看看