Codeforces Round #525 (Div. 2)后俩题

时间:2019-11-06
本文章向大家介绍Codeforces Round #525 (Div. 2)后俩题,主要包括Codeforces Round #525 (Div. 2)后俩题使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

E:https://codeforces.com/contest/1088/problem/E

dp+贪心

题目大意:选择一个k并且选择k个连通块,
要求sigma a[i]/k最大,k尽量大,
对于给定的一颗树,输出最大的分数,不用约分的形式。
题目意思需要进一步解析,
假定有一个最大的连通块,那么
根据贪心的思想,肯定是选择这个连通块,但
又要求k大,所以把所有大小为这个连通块的dp值都计数一遍,
因为我们知道两个最大的连通块不可能有交集,
如果有,肯定是交集部分就是最大值部分,其余的部分都是零,
那么我们从下往上递归求解的过程中,其实也是一种贪心选取,
在计数完当前位置的dp值后,把该位置置为无穷小防止后面再被选取。

#include<bits/stdc++.h>
using namespace std;
#define pb push_back
typedef long long ll;
const int M=3e5+5;
const ll INF=1e18;
ll ans,cnt,dp[M],a[M];
vector<int>g[M];
void dfs(int u,int f,int sign){
    dp[u]=a[u];
    for(int i=0;i<g[u].size();i++){
        int v=g[u][i];
        if(v==f)
            continue;
        dfs(v,u,sign);
        dp[u]+=max(0ll,dp[v]);
    }
    if(sign==1){
        ans=max(ans,dp[u]);
    }
    else if(dp[u]==ans)

            cnt++,dp[u]=-INF;
}
int main(){
    int n;
    ans=-INF;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%I64d",&a[i]);
    for(int u,v, i=1;i<n;i++){
        scanf("%d%d",&u,&v);
        g[u].pb(v);
        g[v].pb(u);
    }
    dfs(1,0,1);
    dfs(1,0,0);
    printf("%I64d %I64d",cnt*ans,cnt);
    return 0;
}
View Code

原文地址:https://www.cnblogs.com/starve/p/11804957.html