GYM-100796C-Minimax Tree【贪心】

来源:互联网 发布:泸沽湖冬天好玩吗 知乎 编辑:程序博客网 时间:2024/06/05 11:15

Bob’s new favourite toy is a rooted tree that consists of n vertices numbered from 1 to n. The number of the root vertex is 1. The tree has l leafs (the root is not considered to be a leaf). Each leaf of the tree has an integer written in it.

This birthday Bob received n - l stickers as a gift: k of them are labelled “min”, and the other n - l - k are labelled “max”. Bob has decided to place the stickers on the internal vertices of the tree, a single sticker on each internal vertex.

Once he has placed all the stickers on the tree, Bob would like to calculate a function f for each vertex v of the tree in the following fashion:

  • If v is a leaf, f(v) is equal to the integer that is written in v.
  • If v has a “min” sticker, f(v) is equal to the minimum value of f(u), where u is any child of v.
  • If v has a “max” sticker, f(v) is equal to the maximum value of f(u), where u is any child of v.

Bob isn’t yet sure how to place his stickers on the tree, but he is interested in the value of f in the root vertex. Given the tree and the stickers, help Bob calculate the minimum and the maximum possible value of f(1)!

Input
The first line contains two space-separated integers n and k (2 ≤ n ≤ 105, 0 ≤ k ≤ n). The second line contains n - 1 space-separated integer numbers p2, p3, …, pn (1 ≤ pi ≤ n). The number pi denotes the parent of the vertex numbered i. The third line contains n space-separated integer numbers a1, a2, …, an (0 ≤ ai ≤ 109). If the vertex i is a leaf, then ai is the number written in that vertex. Otherwise ai will be equal to 0.

It is guaranteed that the given graph will be a tree. It is guaranteed that k + l ≤ n.

Output
In a single line output two integers separated by a space — the minimum and the maximum possible value of f(1).

input
6 1
1 1 2 2 3
0 0 0 1 3 2
output
2 3

题目链接:GYM-100796C

题目大意:给出一棵树,根节点为1.只有叶子节点(有L个)有值,其余节点分为两类

1. min 节点: 当前节点的f值为孩子节点的f值最小的那个2. max 节点: 当前节点的f值为孩子节点的f值最大的那个

有k个min节点,剩余的n-k-L个节点则为max节点,问1节点的f值最大和最小为多少?

题目思路:最小节点值为例:

1.将树全部取孩子节点最大值建好2.从最小值开始取3.如果这个最小值能推到根节点,一路上都取最小值(则为答案)

需要注意的是:如果当前这个节点取最小值后为3。其余节点跟他一样大,那他的父节点不用取最小值。

最大值反着来即可。

以下是代码:

#include <iostream>#include <iomanip>#include <fstream>#include <sstream>#include <cmath>#include <cstdio>#include <cstring>#include <cctype>#include <algorithm>#include <functional>#include <numeric>#include <string>#include <set>#include <map>#include <stack>#include <vector>#include <queue>#include <deque>#include <list>using namespace std;vector <int> e[100005];int a[100005];int a2[100005];int fa[100005];void dfs(int cur){    int len = e[cur].size();    if (len == 0) { return; }    int ret = 0;    for (int i = 0; i < len; i++)    {        int v = e[cur][i];        dfs(v);        ret = max(ret, a[v]);    }    a[cur] = ret;}void dfs2(int cur){    int len = e[cur].size();    if (len == 0) { return; }    int ret = 0;    for (int i = 0; i < len; i++)    {        int v = e[cur][i];        dfs(v);        ret = min(ret, a2[v]);    }    a2[cur] = ret;}struct node{    int id;    int val;}b[100005];bool cmp(node x, node y){    return x.val < y.val;}bool cmp2(node x, node y){    return x.val > y.val;}int main(){    int n,k;    scanf("%d%d",&n,&k);    for (int i = 0; i < n - 1; i++)    {        int num;        scanf("%d",&num);        e[num].push_back(i + 2);        fa[i+2] = num;    }    int lll = 0;    for (int i = 1; i <= n; i++)    {        scanf("%d",&b[i].val);        b[i].id = i;        a[i] = b[i].val;        a2[i] = b[i].val;        if (b[i].val != 0) lll++;    }    sort(b + 1, b + n + 1, cmp);    dfs(1);    int min_ans = 1e9+1, max_ans = 0;    for (int i = 1; i <= n; i++)    {        if (b[i].val != 0)        {            int p = fa[b[i].id];            int w = a[b[i].id];            int cnt = 0;            while(1)            {                int len = e[p].size();                if (len > 1)                {                    int ret = 0;                    for (int j = 0; j < len; j++)                    {                        int v = e[p][j];                        if (a[v] > w)                        {                            cnt++;                            break;                        }                    }                }                if (p == 1) break;                p = fa[p];            }            if (cnt <= k)            {                min_ans = b[i].val;                break;            }        }    }    sort(b + 1, b + n + 1, cmp2);    dfs2(1);    for (int i = 1; i <= n; i++)    {        if (b[i].val != 0)        {            int p = fa[b[i].id];            int w = a2[b[i].id];            int cnt = 0;            while(1)            {                int len = e[p].size();                if (len > 1)                {                    int ret = 0;                    for (int j = 0; j < len; j++)                    {                        int v = e[p][j];                        if (a2[v] < w)                        {                            cnt++;                            break;                        }                    }                }                if (p == 1) break;                p = fa[p];            }            if (cnt <= (n - k - lll))            {                max_ans = b[i].val;                break;            }        }    }    printf("%d %d\n",min_ans,max_ans);    return 0;}
0 0
原创粉丝点击