Codeforcesラウンド#525(DIV。2)D

問題の意味

ツリーから選択します。 K K ように、通信ブロック Σ A K \ FRAC {\和a_iを} {K} 大規模な基礎としてでは、できるだけ大きく、聞かせて K K できるだけ大きく

問題の解決策

あなたが選択した場合我々は、明らかに逆小隊の収集、検討してください K K 、最初は選択します K + 1 K + 1
トン = S K - S + ワット K + 1 T = \ FRAC {S}、{K} - \ FRAC {S + W}、{K + 1}
ので、大きさの比較 K ワット S キロワット\当量S
受注 t 0 T \ GEQ 0 あなたは見つけるでしょう、 k w S キロワット\当量S 条件を知られている、のみ最適であることを選択しました。
しかし k K 最大値の複数の要件のセットから選択されるように、良好です。

しようとしています i ルートノードであり、この最大値は点(同じセット)を降ろす必要があり
、明らかに有します。
f i = m a x ( f j , 0 ) f_i = \合計最大(F_J、0)

最大の和を取得し、再びピットイン d p DP 、最大と同様、その都度、 k + + K ++ 現在のよう d p DP 、次にバックトラック、負の無限大に等しいです。それは重ならないように保証することができます。

#include<bits/stdc++.h>
#define FOR(i,l,r) for(int i=l;i<=r;i++)
#define sf(x) scanf("%d",&x)
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn = 405000;

int n,A[maxn];
vector<int>G[maxn];
ll dp[maxn],ans=-inf,k;

void dfs1(int u,int f){
    dp[u]=A[u];
    for(auto v:G[u]){
        if(v==f)continue;
        dfs1(v,u);
        dp[u]+=max(dp[v],1ll*0);
    }
    ans=max(ans,dp[u]);
}

void dfs2(int u,int f){
    dp[u]=A[u];
    for(auto v:G[u]){
        if(v==f)continue;
        dfs2(v,u);
        dp[u]+=max(dp[v],1ll*0);
    }
    if(dp[u]==ans){
        k++;
        dp[u]=-inf;
    }
}

int main(){
    cin>>n;
    FOR(i,1,n)dp[i]=-inf;
    FOR(i,1,n)scanf("%d",&A[i]);
    FOR(i,1,n-1){
        int u,v;
        scanf("%d%d",&u,&v);
        G[u].push_back(v);
        G[v].push_back(u);
    }
    dfs1(1,-1);
    dfs2(1,-1);
    cout<<ans*k<<" "<<k<<endl;
}

公開された203元の記事 ウォン称賛17 ビュー20000 +

おすすめ

転載: blog.csdn.net/mxYlulu/article/details/104223173