HDU

来源:互联网 发布:中国经济数据统计网 编辑:程序博客网 时间:2024/06/16 12:50

这个题比赛的时候没做出来,看到题解的时候说是什么数链抛分,本菜鸟真的没看懂啊,看了看榜首就用一个dfs做的大佬,看了半天都没看懂,写得很难读,不过看了看别的博客的题解,突然就理解了。

题意:给你n个节点的值,n - 1条边,然后让找你k条路径,从树根开始(就是1),找出每条路径之和为最大值,但是如果之前走过这个节点,那么这个节点的值就变成了0,这是我第二次看到要正方两次dfs的题,第一个好像是uva上的一个也是找路径的题,记得不太清,不过我对于这些糅杂了不同知识点的题就是个白痴。

做法:先把节点用vector和数组存起来,然后用第一次dfs寻找每个路径的最后值,然后用结构体记录下来,排序,然后让权值之和最大的那条路径翻过来dfs一遍,把他经过的点全部标记一遍,然后依次dfs,新求出来的每次结果排序,找出K个最大的就行了,理解了就很简单了,加油!!!

#include <bits/stdc++.h>using namespace std;typedef long long ll;const int maxn = 1e5 + 10;int fa[maxn], val[maxn], vis[maxn], total;int n, k;ll ans[maxn];vector<int> son[maxn];class node{public:    int id;    ll sum;    bool operator < (const node & p1)    {        return  sum > p1.sum;    }}edge[maxn];void dfs1(int now, ll vall){    int son_sum = son[now].size();    if(son_sum == 0)        edge[total].id = now, edge[total++].sum = vall + val[now];    for(int i = 0; i < son_sum; i++)        dfs1(son[now][i],vall + val[now]);}ll dfs2(int now){    if(vis[now])return 0;    vis[now] = 1;    return val[now] + dfs2(fa[now]);}void initial(){    memset(vis, 0, sizeof(vis));    memset(fa, 0, sizeof(fa));    memset(ans, 0, sizeof(ans));    memset(edge, 0, sizeof(edge));    for(int i = 0; i < n; i++)        son[i].clear();}int main(){    ios::sync_with_stdio(false);    int T;    cin >> T;    int kase = 0;    while(T--)    {        initial();        total = 0;        cin >> n >> k;        for(int i = 1; i <= n; i++)            cin >> val[i];        for(int i = 1; i < n; i++)        {            int x, y;            cin >> x >> y;            son[x].push_back(y);            fa[y] = x;        }        dfs1(1, 0);        sort(edge, edge + total);        for(int i = 0; i < total; i++)            ans[i] = dfs2(edge[i].id);        sort(ans, ans + total);        ll ans_sum = 0;        for(int i = total - 1; i >= 0 && k >= 1; i--, k--)            ans_sum += ans[i];        printf("Case #%d: %lld\n",++kase, ans_sum);    }    return 0;}

0 0
原创粉丝点击