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选的子树是否唯一

状态转移方程:dp [ x ] [ 1 ] + = dp [ child ] [ 0 ] ;

dp [ x ] [ 0 ] +  = max ( dp [ child ] [ 0 ] , dp [ child ] [ 1 ] );

而判断唯一性的方程一样的。

AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <algorithm>
#include <map>
using namespace std;
#define maxn 65540
using namespace std;
const int inf = 0x3f3f3f3f;
const int N = 300;

vector<int> child[N];
map<string,int> v;
int dp[N][3];
bool f[N][3]; //唯一性
void DFS(int u)
{
    if(child[u].size()==0)
    {
        dp[u][0]=0;
        dp[u][1]=1;
        return;
    }
    int size=child[u].size();
    for(int i=0;i<size;i++)
    {
        DFS(child[u][i]);
        if(f[child[u][i]][0])
            f[u][1]=1;
        dp[u][1]+=dp[child[u][i]][0];
        if(dp[child[u][i]][0]>dp[child[u][i]][1])
        {
            dp[u][0]+=dp[child[u][i]][0];
            if(f[child[u][i]][0])
                f[u][0]=1;
        }
        else
        {
            dp[u][0]+=dp[child[u][i]][1];
            if(dp[child[u][i]][1]==dp[child[u][i]][0]||f[child[u][i]][1])
                f[u][0]=1;
        }
    }
    dp[u][1]++;
}
int main()
{
    int n;
    while(~scanf("%d",&n) && n)
    {
        memset(dp,0,sizeof(dp));
        memset(f,0,sizeof(f));
        int top = 1;
        string s1,s2;
        cin>>s1;
        v[s1] = top++;
        for(int i=1;i<n;i++)
        {
            cin>>s1>>s2;
            if(!v[s1])
                v[s1]=top++;
            if(!v[s2])
                v[s2]=top++;
            child[v[s2]].push_back(v[s1]);
        }
        DFS(1);
        if(dp[1][1]==dp[1][0])
            printf("%d No\n",dp[1][1]);
        else if(dp[1][1]>dp[1][0])
            printf("%d %s\n",dp[1][1],f[1][1]?"No":"Yes");
        else
            printf("%d %s\n",dp[1][0],f[1][0]?"No":"Yes");
        for(int i = 1;i<=n;i++)
            child[i].clear();
        v.clear();
    }
    return 0;
}

uva

12186 Another Crisis 代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
#define maxn 65540
using namespace std;
const int inf = 0x3f3f3f3f;
const int N = 101000;

int fa[N];
vector<int> child[N];
int dp[N];
int n,k;
void dfs(int x)
{
    int tmp = child[x].size() * k;
    if(tmp%100==0)
        tmp = tmp/100;
    else
        tmp = tmp/100+1;
    vector<int> pps;
    for(int i=0;i<child[x].size();i++)
    {
        int ff = child[x][i],tt = 0;
        dfs(ff);
        tt = dp[ff] ;
        if(child[ff].size()==0)
            tt++;
        pps.push_back(tt);
    }
    int ans = 0;
    sort(pps.begin(),pps.end());
    for(int i=0;i<tmp;i++)
        ans+=pps[i];
    dp[x] = ans;
    return ;
}
int main()
{

    while(~scanf("%d%d",&n,&k) && n+k)
    {
        memset(dp,inf,sizeof(dp));
        for(int i=1;i<=n;i++){
            scanf("%d",&fa[i]);
            child[fa[i]].push_back(i);
        }
        dfs(0);
//        for(int i=0;i<=n;i++)
//            printf("CAS:%d %d\n",i,dp[i]);
        printf("%d\n",dp[0]);
        for(int i=0;i<=n;i++)
            child[i].clear();
    }
    return 0;
}
时间: 2024-10-05 14:09:59

uva 1220 - Party at Hali-Bula 【入门树形dp】的相关文章

HDU1520Anniversary party(入门树形DP)

题意:给出了,参加party的人的关系,但是如果一个人的直接上司出席,那么他就不会出席,每个人有自己的rating.现在想要rating最大. 在网上找了半天,也没找到比较好的树形DP讲解,暂时的感觉是利用DFS搜索的时候,回溯更新. 1.dp[u][0]:表示u这个人不去,那么他的手下v可以选择去或者不去.所以 dp[u][0]+=max(dp[v][0],dp[v][1]); 2.dp[i][1]:表示u这个人去, 那么由题意他的手下肯定不会去,所以dp[u][1]+=dp[v][0]; 状

UVA 12452 Plants vs. Zombies HD SP 树形dp(水

题目链接:点击打开链接 题意: 给定n个点的树[0,n) 开始所有边都是无色. 有3种操作: 1.选一个点染其相连的边 花费100 2.选一个点染其相连的2条边 花费175 3.选一个点染其相连的所有边 花费500 问: 染完所有边的最小花费.边可以重复染,点只能被操作一次. #include <string> #include <iostream> #include <cstdio> #include <algorithm> #include <cm

【POJ 2342】Anniversary party(入门树形dp)

dp[i][0..1]表示i不来/来参加的最大总高兴值. 则dp[i][1]+=dp[v][0](v是i的所有直接下属) dp[i][0]+=max(dp[v][0],dp[v][1]) 没有告诉你树根,dp的方向我第一次写的是用队列维护叶子节点,每次计算完,它的父亲的孩子数量--,如果减到0,就变成叶子加入队列.直到队列空.后来看别人写的两种是读入的时候维护root,还有种方法是记录父亲,然后递推祖先. #include <cstdio> #include <cstring> #

HDU - 1520 Anniversary party (有向入门树形DP)

题目链接:https://vjudge.net/problem/HDU-1520 There is going to be a party to celebrate the 80-th Anniversary of the Ural State University. The University has a hierarchical structure of employees. It means that the supervisor relation forms a tree rooted

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 10859 Placing Lampposts,树形dp

// uva 10859 Placing Lampposts // 树形dp // // 题目的意思是一个无向无环图中,有一些顶点和一些边 // 要在顶点上放置灯笼(灯笼可以照亮与它相邻接的点), // 使得所有的边都能被灯笼照亮,其中可能有一些边被两个灯笼 // 照亮,则要求使得所有边都被灯笼照亮所需灯笼的最小值, // 并且,此时边同时被两个灯笼照亮的数目应尽可能的多 // // 思路是 // d[i][0]表示在节点i不放置灯笼所需的灯笼的最小值 // d[i][1]表示在节点i放置灯笼所

[poj2342]Anniversary party树形dp入门

题意:选出不含直接上下司关系的最大价值. 解题关键:树形dp入门题,注意怎么找出根节点,运用了并查集的思想. 转移方程:dp[i][1]+=dp[j][0];/i是j的子树 dp[i][0]+=max(dp[j][0],dp[j][1]); 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdlib> 5 #include<iostream> 6

UVA - 1218 Perfect Service(树形dp)

题目链接:id=36043">UVA - 1218 Perfect Service 题意 有n台电脑.互相以无根树的方式连接,现要将当中一部分电脑作为server,且要求每台电脑必须连接且仅仅能连接一台server(不包含作为server的电脑).求最少须要多少台电脑作为server. 思路 典型的树形dp问题,那么我们来建立模型. d(u,0):u是server,孩子是不是server均可 d(u,1):u不是server,u的父亲是server,u的孩子不能是server d(u,2)

uva 12186 Another Crisis 树形dp

// uva 12186 Another Crisis 树形dp // // 对于一个节点u,有k个子节点,则至少有c = (k * T - 1) / 100 + 1才能 // 发信,即c / k >= T / 100,则 c 的值为 k * T /100,上取整变成上式 // 将所有的子节点d从小到大排序,取前c个就是d[u]的值 // 紫书上的一题,之前看了好久好久,觉得挺好的,然而一直没做,今天就来 // 体验体验,挺好的一题,注意一下,如果一个节点是叶节点,直接return 1就好 //