zoukankan      html  css  js  c++  java
  • UVa 1220 Party at Hali-Bula (树形DP,最大独立集)

    题意:公司有 n 个人形成一个树形结构,除了老板都有唯一的一个直系上司,要求选尽量多的人,但不能同时选一人上和他的直系上司,问最多能选多少人,并且是不是唯一的方案。

    析:这个题几乎就是树的最大的独立集问题,只不过多一个判断唯一性而已。用两个数组,一个用来记录人数,一个用来判断唯一性。

    d[u][0],表示以 u 为根的子树中,不选 u 点能够得到最大人数,那么d[u][1]就是选 u 点能达到最大人数。

    f[u][0]类似,表示以 u 为根的子树中,不选 u 点是否唯一,那么f[u][1]就是选 u 点是否唯一。

    对于d[u][1]的计算,因为选择了 u,那么 u 的子结点都不能选,所以就是 d[u][1] = sum(d[v][0], v是子结点),当f[v][0] 是不唯一时,f[u][1] 也不唯一。

    对于d[u][0]的计算,因为没有选择了 u,那么它的子结点可以选也可以不选,也就是选最大的,即d[u][0] = sum(max(d[v][0], d[v][1])),那么这个唯一性怎么判断呢?和上面差不多,

    就多了一个,如果d[v][0] == d[v][1],那么这个就是不唯一的了,其他的和上面一样。剩下的就简单了,用DFS即可。

    代码如下:

    #include <iostream>
    #include <cstdio>
    #include <map>
    #include <cstring>
    #include <vector>
    
    using namespace std;
    const int maxn = 200 + 5;
    vector<int> G[maxn];
    bool f[maxn][2];
    int d[maxn][2], n, cnt;//d[u][0] 不选 ,d[u][0] 选
    map<string, int> id;
    
    void init(){//初始化
        for(int i = 1; i <= n; ++i)  G[i].clear();
        memset(f, false, sizeof(f));
        memset(d, 0, sizeof(d));
        cnt = 0;   id.clear();
    }
    
    int getid(const string &s){//获得id
        if(id.count(s))   return id[s];
        return id[s] = ++cnt;
    }
    
    void dfs(int u){
        if(!G[u].size()){//最下端
            d[u][0] = 0;
            d[u][1] = 1;
            return ;
        }
    
        for(int i = 0; i < G[u].size(); ++i){
            int son = G[u][i];
            dfs(son);
            d[u][1] += d[son][0];//d[u][1]的计算
            if(f[son][0])   f[u][1] = true;//判断唯一性
            if(d[son][0] > d[son][1]){//d[u][0]的计算
                d[u][0] += d[son][0];
                if(f[son][0])  f[u][0] = true;
            }
            else if(d[son][0] == d[son][1]){//相等,那就不唯一
                d[u][0] += d[son][0];
                f[u][0] = true;
            }
            else {
                d[u][0] += d[son][1];
                if(f[son][1])  f[u][0] = true;
            }
        }
        ++d[u][1];//别忘了加1
    }
    
    int main(){
        while(scanf("%d", &n) == 1 && n){
            init();
            string s1, s2;
            cin >> s1;  getid(s1);
            for(int i = 0; i < n-1; ++i){
                cin >> s1 >> s2;
                G[getid(s2)].push_back(getid(s1));
            }
    
            dfs(1);
            if(d[1][0] == d[1][1])  printf("%d No
    ", d[1][0]);//判断谁在数更大
            else if(d[1][0] > d[1][1])  printf("%d %s
    ", d[1][0], f[1][0] ? "No" : "Yes");
            else  printf("%d %s
    ", d[1][1], f[1][1] ? "No" : "Yes");
        }
        return 0;
    }
    
  • 相关阅读:
    破局人工智能:构建AI,与腾讯云一起探索语音应用场景
    破局人工智能:构建AI,与腾讯云一起探索语音应用场景
    浅谈 Objective-C Associated Objects
    一个封装了的选项卡效果js
    getElementById 用法的一个技巧
    用 Javascript 实现的“Dual listbox”(双向选择器)
    Jsp 连接 mySQL、Oracle 数据库备忘(Windows平台)
    我为什么坚持写博客?
    内存模型
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
  • 原文地址:https://www.cnblogs.com/dwtfukgv/p/5650885.html
Copyright © 2011-2022 走看看