SGU195 New Year Bonus Grant

题解:

树的独立集问题。。。

树的独立集问题在dp上有两种写法,一种是搜索,一种是刷表。

这题是刷表

题意:给出一棵树,根节点是1,要求根据以下要求选择最多的节点:

①不能选择1

②若选择当前节点,那么该节点的父节点和儿子都不能选择。

③若某节点的某一个儿子节点被选择,那么该节点的其他儿子不能被选择。(中文题意链接:http://blog.csdn.net/qian99/article/details/16970341)

关键是对于第3种情况。

dp[u][0]表示当前点不选,dp[u][1]表示当前点选

分为2种第一种是所有儿子都不选择,第二种选择一个最优儿子,那么等价于先全部不选择儿子。然后一定要选儿子的话,选dp[v][1]-dp[v][0]最大的就行了。具体看代码

代码:

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdio>
using namespace std;
#define pb push_back
#define mp make_pair
#define se second
#define fs first
#define LL long long
#define CLR(x) memset(x,0,sizeof x)
#define MC(x,y) memcpy(x,y,sizeof(x))
#define SZ(x) ((int)(x).size())
#define FOR(it,c) for(__typeof((c).begin()) it=(c).begin();it!=(c).end();it++)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef pair<int,int> P;
const double eps=1e-9;
const int N=5e5+10;
const int M=1e3+10;
const LL mod=1000000007;
const int INF=1e9+10;

int n,cnt,num;
int head[N],dp[N][2],ans[N],to[N];

struct Edge{
    int v,nxt;
}edge[N*2];

void Init(){
    cnt=0;
    num=0;
    memset(head,-1,sizeof(head));
}

void addEdge(int u,int v){
    edge[cnt].v=v;
    edge[cnt].nxt=head[u];
    head[u]=cnt++;
}

void dfs(int u){
    dp[u][0]=0,dp[u][1]=1000;
    int tmp=-INF;
    for(int i=head[u];i!=-1;i=edge[i].nxt){
        int v=edge[i].v;
        dfs(v);
        dp[u][1]+=dp[v][0];
        dp[u][0]+=dp[v][0];
        if(dp[v][1]-dp[v][0]>tmp){
            tmp=dp[v][1]-dp[v][0];
            to[u]=v;
        }
    }
    if(tmp>0) dp[u][0]+=tmp;
    else      to[u]=0;
}

void Find_path(int u,int k){
    int Best=-1;
    if(k==0) Best=to[u];
    if(k==1) ans[num++]=u;
    for(int i=head[u];i!=-1;i=edge[i].nxt){
        int v=edge[i].v;
        if(k==1) Find_path(v,0);
        if(k==0){
            if(v==Best) Find_path(v,1);
            else        Find_path(v,0);
        }
    }
}

int main(){
    Init();
    scanf("%d",&n);
    for(int i=2;i<=n;i++){
        int x;
        scanf("%d",&x);
        addEdge(x,i);
    }
    dfs(1);
    printf("%d\n",dp[1][0]);
    Find_path(1,0);
    sort(ans,ans+num);
    for(int i=0;i<num;i++) printf("%d%c",ans[i],(i==num-1?‘\n‘:‘ ‘));
    return 0;
}
时间: 2024-10-19 07:03:44

SGU195 New Year Bonus Grant的相关文章

ZOJ 2315 New Year Bonus Grant

New Year Bonus Grant Time Limit: 5000ms Memory Limit: 32768KB This problem will be judged on ZJU. Original ID: 231564-bit integer IO format: %lld      Java class name: Main Special Judge All programmers of Mocrosoft software company are organized in

1212 New Year Bonus Grant

Problem Description All programmers of Mocrosoft software company are organized in a strict subordination hierarchy. Every programmer has exactly one chief, except Bill Hates who is also the head of the company and has no chief. Due to the celebratio

ASC1 C New Year Bonus Grant

题意:给你一棵树,有三种规则 1)根节点不能选 2)选了这个点 它 的父亲节点和子节点都不能选. 3)一个点只能选其中的一个子节点. 问你选点的最大值 解题思路:树形DP.DP[I][1/0]表示选或不选最大的. 解题代码: 1 // File Name: c.cpp 2 // Author: darkdream 3 // Created Time: 2015年03月21日 星期六 14时55分57秒 4 5 #include<vector> 6 #include<list> 7

zoj 2315 New Year Bonus Grant 解题报告

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1315 题目意思:Bill Hates 是公司的老总,她管辖着很多程序员,每个程序员都有各自的上头.现在为了庆祝2013年的到来,要向这些程序员发放新年奖金.不过要遵循一些规则: 1.每个程序员要不把奖金给予她的其中一个下属,要把就等着她的上司发奖金给她. 2.每个程序员不能同时接收奖金和分发奖金. 3.如果程序员要把奖金给予她的下属,她的下属只能是一个,不能是多个.

zoj2315New Year Bonus Grant Dp

树dp吧,就是它取了 就不能取它儿子,它儿子最多有一个可以取. 然后对于每种dp[x][1] 表示 x 取了, dp[x][1] = ∑ dp[son[x][0] +1,但是如果他是1  ,他自己不能取自己,这里要注意下. dp[x][0]= max((∑dp[son[x]][0])-dp[son[x]][0] + dp[son[x]][1]; #include<iostream> #include<cstdio> #include<cstring> #include&

【树形dp】SGU 195 New Year Bonus Grant

通道 题意: 给出一棵树,根节点是1,要求根据以下要求选择最多的节点: ①不能选择1 ②若选择当前节点,那么该节点的父节点和儿子都不能选择. ③若某节点的某一个儿子节点被选择,那么该节点的其他儿子不能被选择 样例分析图: 思路:用dp[u][2]表示u节点是否被选择的最大值,则dp[u][1]=sum{dp[v][0]}+1,dp[u][0]=max(sum{dp[v][0]}  ,  sum{dp[v][0]}-min{dp[v][0]+dp[v][1]}); 代码: #include<cst

[ACdream 1212 New Year Bonus Grant]贪心

题意:员工之间形成一棵树,上级可以给下级发奖金,任何一个人最多可以给一个下级发,并且发了奖金后就不能接受奖金.求总共最多可以产生多少的奖金流动 思路:每次选择没有下级并且有上级的员工a,令它的上级为b,那么让b给a发奖金,之后把a和b从树中删掉,这样处理直到不存在这样的员工a.也就是说每次让叶子员工接受奖金.简单证明:对于最优情况,叶子和它的兄弟集合还有它的父亲一定有一个接受了奖金,否则可以选叶子接受从父亲发的奖金,这样比原来增加了1个奖金:假设父亲接受了奖金或者兄弟接受了奖金,那么换成自己接收

SGU 195. New Year Bonus Grant

时间限制:0.75s 空间限制:4M 题意: 在一颗树(最多500000个节点)中,可以对节点染色,但是一个节点染了色后,它的父节点和兄弟节点都不能再染了,求最大的染色节点数,并输出所有染色节点. Solution: 一开始写了一个树形DP 后来看到有人说题目的输入是从上到下的...直接倒过来贪心就好了.ORZ 代码: #include <iostream> #include <cstdio> using namespace std; const int INF = 510000;

ASC #1

开始套题训练,第一套ASC题目,记住不放过每一题,多独立思考. Problem A ZOJ 2313 Chinese Girls' Amusement 循环节 题意:给定n,为圆环长度,求k <= n/2,从1出发,每次顺时针方向走k步,即1->k+1->2*k+1,直到遇到一个已经走过的点结束,要求最终把所有点访问一遍,最后回到1,使得k尽量大. 代码: Problem B ZOJ 2314 Reactor Cooling 无源汇上下界网络流 题意:经典题,有上下界无源无汇的可行流,对