您的位置:首页 > 其它

2015上海邀请赛——Game

2015-07-11 15:06 337 查看
这道题也是我看了题解才懂得,其实并不是很难,题目意思是,有一棵树,每个节点上有一个权值,从根节点走到尾节点算是一个链,链的权值为链上节点的权值和,但是有个要求,就是每个权值只能被算一次,问你前K个链的权值和的最大值是多少。

这道题的解题思路就是搜索,先搜索出最大的一条链,然后把最大的这条链上的权值都置为零,然后以此类推,再找出剩下最大的,最后将所有的链排序,将前K个相加即可。代码模仿大神,神奇的地方在于DFS过程的简洁,再次膜拜。

/*#########################################################################
# File Name: game.cpp
# Author: CaoLei
# Created Time: 2015/7/11 10:39:37
#########################################################################*/

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <set>
#include <queue>
#include <map>
using namespace std;
#define MAX(x,y) (((x)>(y))?(x):(y))
#define MIN(x,y) (((x)<(y))?(x):(y))
#define N 100010
#define pi acos(-1.0)
#define inf 100000000
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
int n,k,it;
int fnext
,val
;
struct edge{
    int u,v;
    int next;
}e
;

priority_queue<ll>q;
void addedge(int u,int v){
    e[it].u=u;
    e[it].v=v;
    e[it].next=fnext[u];
    fnext[u]=it++;
}

ll dfs(int root){
    ll maxval=0;
    for(int i=fnext[root];i!=-1;i=e[i].next){
        int v=e[i].v;
        ll val=dfs(v);
        if(val>maxval){
            if(maxval!=0) q.push(maxval);
            maxval=val;
        }
        else q.push(val); 
    }
    return maxval+val[root];
}

int main(){
    //freopen("in.txt","r",stdin);
    int t,cas,a,b;
    scanf("%d",&t);
    for(cas=1;cas<=t;cas++){
        it=1;
        printf("Case #%d: ",cas);
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++){
            scanf("%d",&val[i]);
            fnext[i]=-1;
        }        
        for(int i=1;i<n;i++){
            scanf("%d%d",&a,&b);
            addedge(a,b);
        }
        while(!q.empty()) q.pop();
        ll ans=dfs(1);
        for(int i=2;i<=k&&!q.empty();i++){
            ans+=q.top();
            q.pop();
        }
        printf("%lld\n",ans);
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: