1. 程式人生 > >Codeforces Round #525 (Div. 2) F. Ehab and a weird weight formula(思維+貪心)

Codeforces Round #525 (Div. 2) F. Ehab and a weird weight formula(思維+貪心)

F. Ehab and a weird weight formula

time limit per test

2.5 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

You're given a tree consisting of nn nodes. Every node uu has a weight auau. It is guaranteed that there is only one node with minimum weight in the tree. For every node uu (except for the node with the minimum weight), it must have a neighbor vv such that av<auav<au. You should construct a tree to minimize the weight ww calculated as follows:

  • For every node uu, degu⋅audegu⋅au is added to ww (degudegu is the number of edges containing node uu).
  • For every edge {u,v}{u,v}, ⌈log2(dist(u,v))⌉⋅min(au,av)⌈log2(dist(u,v))⌉⋅min(au,av) is added to ww, where dist(u,v)dist(u,v) is the number of edges in the path from uuto vv in the given tree.

Input

The first line contains the integer nn (2≤n≤5⋅105)(2≤n≤5⋅105), the number of nodes in the tree.

The second line contains nn space-separated integers a1,a2,…,ana1,a2,…,an (1≤ai≤109)(1≤ai≤109), the weights of the nodes.

The next n−1n−1 lines, each contains 2 space-separated integers uu and vv (1≤u,v≤n)(1≤u,v≤n) which means there's an edge between uu and vv.

Output

Output one integer, the minimum possible value for ww.

Examples

input

Copy

3
1 2 3
1 2
1 3

output

Copy

7

input

Copy

5
4 5 3 7 8
1 2
1 3
3 4
4 5

output

Copy

40

Note

In the first sample, the tree itself minimizes the value of ww.

In the second sample, the optimal tree is:

題意:

給你一顆包含n個節點的無向樹,每個節點都有值。保證這棵樹除了最小值節點,其他節點均存在一條鄰邊,使得邊的另一點的值比它小。現在讓你重構這棵樹,使得總權值最小。

總權值=每個節點的值*這個節點的度+每條邊的權值*min( log2(其一點u到另任意一點v的最小距離)*點v的值 )。

思路:

由紅色部分我們可以得出,當確定最小值的節點為根以後,從根往下每個節點的權值一定是依次增大的。所以就可以採用近似貪心的思想,

考慮將兩種貢獻直接一次按每條邊的貢獻算,則對於任意點對(u,v),設a[u]>a[v],

則總權值=a[u]+min(a[v]+a[v]*log2(dist[u][v]))  注意log2是向上取整(題幹中有說),所以一次直接列舉u的第2的i次方個祖先節點,對於每2的i次方個祖先,深度越低的祖先權值越小,所以列舉i,都是直接用u的第2的i次方的祖先來當v(即重新構的圖中,u直接連向v)。

注意根節點要特判。(因為可能不是正好是u的第2的整數次方個祖先)

最終總複雜度是O(nlogn)。

說難也不難,但是思維難度很高,還需要更多的思考和練習。

#include <bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f3f3f3f3fLL
using namespace std;
const int maxn=5e5+10;
vector<ll>vc[maxn];
ll a[maxn],dp[maxn][21],c[maxn];
int n,rt;
bool jud;
ll ans,cnt;
void dfs(int u,int fa)
{
    dp[u][0]=fa;
    for(int i=1;i<=20;i++)
    {
        if(dp[u][i-1]==-1) break;
        dp[u][i]=dp[dp[u][i-1]][i-1];
    }
    ll mi=inf;
    for(int i=0;i<=20;i++)
    {
        mi=min(mi,a[u]+(ll)(i+1)*a[dp[u][i]]);
        if(dp[u][i+1]==-1)
        {
            mi=min(mi,a[u]+(ll)a[rt]*(i+2));
            break;
        }
    }
    if(u!=rt) ans+=mi;
    for(int i=0;i<vc[u].size();i++)
    {
        int v=vc[u][i];
        if(v!=fa) {
        dfs(v,u);
        }
    }
}
int main()
{
    scanf("%d",&n);
    rt=1;
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
        if(a[i]<a[rt]) rt=i;
    }
    for(int i=1;i<n;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        vc[x].push_back(y);
        vc[y].push_back(x);
    }
    ans=0;
    memset(dp,-1,sizeof(dp));
    dfs(rt,-1);
    printf("%lld\n",ans);
    return 0;
}