51Nod-1273-旅行计划

来源:互联网 发布:mac版lol 编辑:程序博客网 时间:2024/06/05 01:57

ACM模版

描述

描述

题解

通过题意,我们可以清晰的知道,每天到达的结点一定是叶子结点,所以我们先 dfs 遍历一遍树,将说有的叶子结点xvn2,这里我们附带还要入一个叶子节点的深度d,为了保证未经过的城市最多,当然,光这样还是无法保证未经过的城市最多,因为不同的叶子结点到根节点的路径会有重合,所以我们需要从所有叶子结点开始向前访问一遍(访问之前需要进行一次排序,保证未经过的城市最多,同样多时,保证编号最小),求出有多少个未访问过的结点cnt,同样存入vn2中。

最后,我们只需要将vn2根据cnt的大小进行一下排序输出即可。说到底,这里是一个贪心,搞不懂话题为啥是树形DP,难道是为了迷惑我们?

代码

#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <vector>#define pb push_backusing namespace std;const int MAXN = 1e5 + 10;struct node{    int to, next;} edge[MAXN];int tot = 0;int head[MAXN], deep[MAXN];void add(int u, int v){    edge[++tot].to = v;    edge[tot].next = head[u];    head[u] = tot;}struct node2{    int x, d, cnt;    node2(int x_, int d_, int cnt_ = 0) : x(x_), d(d_), cnt(cnt_) {}    bool operator < (const node2 &b) const    {        return d > b.d || (d == b.d && x < b.x);    }};vector<node2> vn2;int pre[MAXN];//  遍历树,存储 pre[],将叶子结点与其深度入 vn2void dfs(int x, int pr){    pre[x] = pr;    bool flag = false;    for (int i = head[x]; i; i = edge[i].next)    {        int v = edge[i].to;        if (v == pr)        {            continue;        }        else        {            flag = true;        }        deep[v] = deep[x] + 1;        dfs(v, x);    }    if (!flag)    {        vn2.pb(node2(x, deep[x]));    }}bool cmp(node2 a, node2 b){    return a.cnt > b.cnt || (a.cnt == b.cnt && a.x < b.x);}bool vis[MAXN];int main(){    int N, K;    cin >> N >> K;    int v;    for (int i = 1; i < N; i++)    {        scanf("%d", &v);        add(v, i);        add(i, v);    }    deep[K] = 1;    vis[K] = 1;    dfs(K, -1);    sort(vn2.begin(), vn2.end());           //  根据深度从大到小排序    for (int i = 0; i < vn2.size(); i++)    //  获取叶子结点到根路径对应未访问结点数    {        node2 leaf = vn2[i];        int x = leaf.x, cnt = 0;        while (x != -1)        {            if (!vis[x])            {                cnt++;                vis[x] = 1;            }            else            {                break;            }            x = pre[x];        }        vn2[i].cnt = cnt;    }    printf("%d\n", K);    sort(vn2.begin(), vn2.end(), cmp);      //  根据未访问节点数排序    for (int i = 0; i < vn2.size(); i++)    {        if (vn2[i].cnt)        {            printf("%d\n", vn2[i].x);        }    }    return 0;}
0 0