Facebook Hacker Cup 2015 Round 1--Corporate Gifting(树形动态规划)

原题:https://www.facebook.com/hackercup/problems.php?pid=759650454070547&round=344496159068801

题意:给定一颗有根树,在树上下层的节点要给上层节点礼物,根节点的礼物则给慈善会,但是给礼物有个条件就是你不能送你的父节点已经送出的礼物。问满足要求的最少花费。

题解:这个题卡了一段时间,类似于染色问题,可以用树形动态规划求解。因为已知节点个数为N,则我们单个节点的最大花费不会超过log2(N) = 18。

1. 设dp[i][j]是在i节点花费j时以i为根节点的子树所需要的总开销。

2. 则dp[i][j] = sum{min{dp[son][k],1 <= k <= 18且k != j},son为i的每个子节点};

比赛的时候一开始使用DFS,没注意到节点规模在树成链状时会导致暴栈。但是时间已经来不及了,很遗憾没有进入round 2。

代码如下:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
#define maxN 200005
#define maxM 18

vector<vector<int> > sons;
int N;
int minCost[maxN][maxM];

struct node
{
    int ID;
    int depth;
    friend bool operator< (node x,node y)
    {
        return x.depth > y.depth;
    }
}employee[maxN];

int BFS()
{
    for(int i = 1;i <= N;i++)
    {
        employee[i].ID = i;
    }
    employee[1].depth = 0;
    int now,next;
    int sonSize;
    queue<int> q;
    q.push(1);
    while(!q.empty())
    {
        now = q.front();
        q.pop();
        sonSize = sons[now].size();
        for(int i = 0;i < sonSize;i++)
        {
            next = sons[now][i];
            q.push(next);
            employee[next].depth = employee[now].depth+1;
        }
    }
}

int dp()
{
    int fa,son,sonSize;
    int i,j,k,m;
    int tmpMinCost;
    BFS();
    sort(employee+1,employee+N+1);
    for(i = 1;i <= N;i++)
    {
        fa = employee[i].ID;
        sonSize = sons[fa].size();
        for(j = 1;j <= maxM;j++)
        {
            minCost[fa][j] = j;
            for(k = 0;k < sonSize;k++)
            {
                son = sons[fa][k];
                tmpMinCost = INT_MAX;
                for(int m = 1;m <= maxM;m++)
                {
                    if(m == j)
                        continue;
                    tmpMinCost = min(tmpMinCost,minCost[son][m]);
                }
                minCost[fa][j] += tmpMinCost;
            }
        }
    }
    int ans = INT_MAX;
    for(i = 1;i <= maxM;i++)
    {
        ans = min(ans,minCost[1][i]);
    }
    return ans;
}

int main()
{
    freopen("corporate_gifting.txt","r",stdin);
    freopen("out.txt","w",stdout);
    int T;
    int fa;
    scanf("%d",&T);
    for(int i = 1;i <= T;i++)
    {
        scanf("%d",&N);
        vector<vector<int> >().swap(sons);
        sons.resize(N+1);
        for(int j = 1;j <= N;j++)
        {
            scanf("%d",&fa);
            sons[fa].push_back(j);
        }
        printf("Case #%d; %d\n",i,dp());
    }
    return 0;
}
时间: 2024-12-21 01:17:34

Facebook Hacker Cup 2015 Round 1--Corporate Gifting(树形动态规划)的相关文章

Facebook Hacker Cup 2015 Round 1--Winning at Sports(动态规划)

原题:https://www.facebook.com/hackercup/problems.php?pid=688426044611322&round=344496159068801 题意:你和一个朋友玩足球游戏,分数从0-0开始,最终你总是赢,并且你主要有两种方式赢,第一种stressFree方式你肯定要进第一个球并且总是比你的朋友分数高,第二种stressFull方式除了你的朋友达到最终分数时,在游戏中你不可能比你的朋友分数高.给出一个比分,请分别输出在两种情况下你能赢的方式. 题解:类似

Facebook Hacker Cup 2015 Round 1 Homework(附带测试数据)

题目描述: Homework10 points Your first-grade math teacher, Mr. Book, has just introduced you to an amazing new concept - primes! According to your notes, a prime is a positive integer greater than 1 that is divisible by only 1 and itself. Primes seem fun

Facebook Hacker Cup 2015 Round 1 Autocomplete (附带测试数据)

题目描述: Autocomplete25 points Since you crave state-of-the-art technology, you've just purchased a phone with a great new feature: autocomplete! Your phone's version of autocomplete has some pros and cons. On the one hand, it's very cautious. It only a

Facebook Hacker Cup 2015 Round 1 Winning at Sports (附带测试数据)

题目描述: Winning at Sports25 points In the game of Sports, the object is have more points than the other team after a certain amount of time has elapsed. Scores are denoted by two hyphen-separated integers. For example, scores may include 3-2, 4-1, or 1

Facebook Hacker Cup 2015 Round 1--Autocomplete(字典树新建与查询)

题意:给定N个字符串,让你依次先输入到手机的字典中,再打印出来,打印的时候我们只需要输出字符串的前缀或者全部字符串,要求此前缀不是以往任何字符串的前缀. 题解:典型的字典树,可以利用结构体数组方便的新建与查询,速度比链表更快.只需在插入字符串时统计最长相同的前缀即可. 代码如下: #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define maxN 1000005

Facebook Hacker Cup 2015 Round 1--Homework(筛选法求素数)

题意:给定A,B,K(A<=B)三个数,问在[A,B]范围内的数素数因子个数为K的个数. 题解:典型的筛选法求素数.首先建立一个保存素数因子个数的数组factorNum[],以及到n为止含有素数因子个数为k的二维数组sumNum[n][k]. factorNum可以由筛选法确定,初始化数组为0. 1. 从小到大遍历给定最大范围内的数,若遍历到数n时,factorNum[n]=0则说明这个数是素数(前面没有它的因子). 2. 然后通过增加n的倍数,来筛选出最大范围内含有素数因子n的数. sumNu

Facebook Hacker Cup 2015 Round 1 --- Homework

给一个区间,求该区间内 质因子个数等于k的数 的个数. 暴力预处理一下啦 #include<cstdio> #include<cstring> using namespace std; const int maxn=10000010; bool pri[maxn]; int cnt[maxn]; void init() { memset(pri,1,sizeof pri); memset(cnt,0,sizeof cnt); for(int i=2;i<=10000000;i

Facebook Hacker Cup 2015 Round 1 --- Autocomplete

Since you crave state-of-the-art technology, you've just purchased a phone with a great new feature: autocomplete! Your phone's version of autocomplete has some pros and cons. On the one hand, it's very cautious. It only autocompletes a word when it

Facebook Hacker Cup 2015 Round 1 --- Winning at Sports

In the game of Sports, the object is have more points than the other team after a certain amount of time has elapsed. Scores are denoted by two hyphen-separated integers. For example, scores may include 3-2, 4-1, or 10-0. The first number is how many