Uva 1220,Hali-Bula 的晚会

题目链接:https://uva.onlinejudge.org/external/12/1220.pdf

题意: 公司n个人,形成一个数状结构,选出最大独立集,并且看是否是唯一解。

分析:

d(i) 是 节点 i 的最优值, i 只有两种决策,就是选和不选。 转移方程:

d(i) = max {1+Σ1d(j),Σ2d(j)}; Σ1是所有孙子节点,Σ2是所有儿子节点。

那么状态的定义d(i,0),节点 i 不选,d(i,1),节点 i 选。

那么状态转移方程就是:

是否唯一 f(v,0) = 1 表示唯一, f(v,1) = 0 不唯一。

d(u,1) = sum{d(v,0)}(v是u的子节点),当所有 f(v,0) = 1,d(u,1) = 1;

d(u,0) = sum{max(d(v,0),d(v,1))}, if (d(v,0)==d(v,1)) f(u,0) = 0,取的对应的f()==0,f(u,0) = 0;

存树形结构,一个较好的方式用邻接表,每个字符串对应一个ID,可以用map<string,int>dict,有一个较好的函数,dict.count(s),s字符串出现的次数。

#include <bits/stdc++.h>
using namespace std;

const int maxn = 200+5;
int cnt;
int n;
vector<int> sons[maxn];
int d[maxn][2],f[maxn][2];

map<string,int> dict;

int ID(const string &s) {
    if(!dict.count(s)) dict[s] = cnt++;
    return dict[s];
}

int dp(int u,int k) {
    f[u][k] = 1;
    d[u][k] = k;
    for(int i=0;i<sons[u].size();i++) {
        int v = sons[u][i];
        if(k==1) {
            d[u][1] +=dp(v,0);
            if(!f[v][0]) f[u][1] = 0;
        }
        else {
            d[u][0] +=max(dp(v,0),dp(v,1));
            if(d[v][0]==d[v][1]) f[u][k] = 0;
            else if(d[v][0]>d[v][1]&&!f[v][0]) f[u][k] = 0;
            else if(d[v][1]>d[v][0]&&!f[v][1]) f[u][k] = 0;
        }
    }
    return d[u][k];
}

int main()
{
    string s,s2;
    while(cin>>n>>s) {
        cnt = 0;
        dict.clear();

        for(int i=0;i<n;i++)
            sons[i].clear();

        ID(s);
        for(int i=0;i<n-1;i++) {
            cin>>s>>s2;
            sons[ID(s2)].push_back(ID(s));
        }

        printf("%d ",max(dp(0,0),dp(0,1)));
        bool unique = false;
        if(d[0][0]>d[0][1]&&f[0][0]) unique = true;
        if(d[0][1]>d[0][0]&&f[1][0]) unique = true;
        if(unique) printf("Yes\n");
        else printf("No\n");

    }

    return 0;
}

时间: 2024-12-06 07:12:55

Uva 1220,Hali-Bula 的晚会的相关文章

Party at Hali-Bula UVA - 1220 (树形dp)

Party at Hali-Bula UVA - 1220 题意:选一个公司的人去参加晚会,要求不能选有直接上下级关系的人,问最多选多少人去,并判断方案是否唯一. 树的最大独立集,并判断是否唯一. d[u][1]表示选u,d[u][0]表示不选u f[u][1]==1表示选u的情况下唯一,f[u][1]==0表示不唯一 f[u][0]为不选u的情况下的唯一性 1 #include <cstdio> 2 #include <bits/stdc++.h> 3 using namespa

uva 1220 - Party at Hali-Bula 【入门树形dp】

题目:uva 1220 - Party at Hali-Bula 题意:一个公司员工要举行聚会,要求任意一个人不能和他的直接上司同时到场,一个员工只有一个支系上司,现在求最多有多少人到场,并且方案是否唯一 分析:分析发现是要求一个树的最大独立集.这里可以用树形dp解决. 定义dp[x][0]:表示在 i 点不选 i 点的以 x 为子树的最大独立集 而dp[x][1] 表示x到场的最大独立集 定义f [x][0]:表示以x为根且x点不选的子树是否唯一 ,f[x][1]表示以x为根且x选的子树是否唯

UVa 1220 Hali-Bula的晚会(树的最大独立集)

https://vjudge.net/problem/UVA-1220 题意: 公司里有n个人形成一个树状结构,即除了老板以外每个员工都有唯一的直属上司.要求选尽量多的人,但不能同时选择一个人和他的直属上司.输出最多能选多少人并判断是否唯一. 思路: 树的最大独立集问题.就是需要额外判定是否是唯一的. 因为输入的都是人名,所以首先就是用map容器来处理,上下属的关系就用vector容器来处理. d[u][1]表示以u为根的子树中,选u点能得到的最大人数,f[u][1]判断这种方案是否唯一. d[

UVA - 1220 Party at Hali-Bula

题目大意:n 个人形成一个关系树,每个节点代表一个人,节点的根表示这个人的唯一的直接上司,只有根没有上司.要求选取一部分人出来,使得每 2 个人之间不能有直接的上下级的关系, 求最多能选多少个人出来,并且求出获得最大人数的选人方案是否唯一. 解题思路:分析发现是要求一个树的最大独立集.这里可以用树形 DP 解决. 定义dp[x][0]:表示在 i 点不选 i 点的以 x 为子树的最大独立集 而dp[x][1] 表示x到场的最大独立集 定义f [x][0]:表示以x为根且x点不选的子树是否唯一 ,

UVA 1220 Party at Hali-Bula (树形DP)

求一棵数的最大独立集结点个数并判断方案是否唯一. dp[i][j]表示以i为根的子树的最大独立集,j的取值为选和不选. 决策: 当选择i时,就不能选择它的子结点. 当不选i时,它的子结点可选可不选. 判断唯一性:当选择的某个子节点方案不唯一,父节点的方案就不唯一,或者某个子节点选或不选方案数一样. 转移顺序:按照拓扑序转移或dfs都可以. #include<bits/stdc++.h> using namespace std; const int maxn = 201; const int p

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]就是选

树状DP

紫皮,各种,非原创 uva 12186 工人的请愿书 下属中不小于 T% 的人签字时会签字递给上级,问至少需要多少人签字才能传给老板 #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <cstdlib> #include <map> #include <queu

HDU 1520 Anniversary party

http://acm.hdu.edu.cn/showproblem.php?pid=1520 题意: 将有一个党庆祝乌拉尔国立大学80周年.大学有一个员工的层次结构.这意味着监督关系形成了一个树根源于校长VE Tretyakov.为了使党对每个人都有趣,主任不想让一个雇员和他或她的直接主管在场.人事局已评估每个员工的欢乐性,所以每个人都有一定数量(评级)附加到他或她.你的任务是制作一个客人的列表,其中有最大可能的客人的欢乐度评分的总和. 思路: 这道题目就是UVa 1220的减弱版,比较基本的树

树的最大独立集

p280 9.4.2 原问题d(i)是以i为根节点,子问题是以i的儿子节点和以i的孙子节点为根节点. 讲解中的“当计算出一个d(i)后,用它去更新i的父亲和祖父节点的累加值”,对应到代码,需要从树的叶子节点开始计算d(i),可以用dfs 下面是 poj 2342的代码,例题9-13 UVa 1220 对应 poj 3342 #define _CRT_SECURE_NO_WARNINGS #include<cstdio> #include<cstdlib> #include<c