Boboniu and Jianghu

Since Boboniu finished building his Jianghu, he has been doing Kungfu on these mountains every day.

Boboniu designs a map for his n n n mountains. He uses n − 1 n−1 n1 roads to connect all n n n mountains. Every pair of mountains is connected via roads.

For the i i i-th mountain, Boboniu estimated the tiredness of doing Kungfu on the top of it as t i t_i ti. He also estimated the height of each mountain as h i h_i hi.

A path is a sequence of mountains M M M such that for each i i i ( 1 ≤ i < ∣ M ∣ ) (1≤i<|M|) (1i<M), there exists a road between M i M_i Mi and M i + 1 M_{i+1} Mi+1. Boboniu would regard the path as a challenge if for each i i i ( 1 ≤ i < ∣ M ∣ ) (1≤i<|M|) (1i<M), h M i ≤ h M i + 1 h_{M_i}≤h_{M_{i+1}} hMihMi+1.

Boboniu wants to divide all n − 1 n−1 n1 roads into several challenges. Note that each road must appear in exactly one challenge, but a mountain may appear in several challenges.

Boboniu wants to minimize the total tiredness to do all the challenges. The tiredness of a challenge M M M is the sum of tiredness of all mountains in it, i.e. ∑ i = 1 ∣ M ∣ t M i ∑_{i=1}^{|M|}t_{M_i} i=1MtMi.

He asked you to find the minimum total tiredness. As a reward for your work, you’ll become a guardian in his Jianghu.

Input
The first line contains a single integer n n n ( 2 ≤ n ≤ 2 ⋅ 1 0 5 ) (2≤n≤2⋅10^5) (2n2105), denoting the number of the mountains.

The second line contains n n n integers t 1 , t 2 , … , t n t_1,t_2,…,t_n t1,t2,,tn ( 1 ≤ t i ≤ 1 0 6 ) (1≤t_i≤10^6) (1ti106), denoting the tiredness for Boboniu to do Kungfu on each mountain.

The third line contains n n n integers h 1 , h 2 , … , h n h_1,h_2,…,h_n h1,h2,,hn ( 1 ≤ h i ≤ 1 0 6 ) (1≤h_i≤10^6) (1hi106), denoting the height of each mountain.

Each of the following n − 1 n−1 n1 lines contains two integers u i , v i u_i, v_i ui,vi ( 1 ≤ u i , v i ≤ n , u i ≠ v i ) (1≤u_i,v_i≤n,u_i≠v_i) (1ui,vin,ui=vi), denoting the ends of the road. It’s guaranteed that all mountains are connected via roads.

Output
Print one integer: the smallest sum of tiredness of all challenges.

Examples

input
5
40 10 30 50 20
2 3 2 3 1
1 2
1 3
2 4
2 5
output
160
input
5
1000000 1 1 1 1
1000000 1 1 1 1
1 2
1 3
1 4
1 5
output
4000004
input
10
510916 760492 684704 32545 484888 933975 116895 77095 127679 989957
402815 705067 705067 705067 623759 103335 749243 138306 138306 844737
1 2
3 2
4 3
1 5
6 4
6 7
8 7
8 9
9 10
output
6390572

Note
For the first example:
Boboniu and Jianghu_第1张图片
In the picture, the lighter a point is, the higher the mountain it represents. One of the best divisions is:

  • Challenge 1 1 1: 3 → 1 → 2 3→1→2 312
  • Challenge 2 2 2: 5 → 2 → 4 5→2→4 524

The total tiredness of Boboniu is ( 30 + 40 + 10 ) + ( 20 + 10 + 50 ) = 160 (30+40+10)+(20+10+50)=160 (30+40+10)+(20+10+50)=160. It can be shown that this is the minimum total tiredness.
思路参考(照搬)

纯树形 d p dp dp,但是状态的选择以及状态转移的贪心策略不太容易想到,并且还要注意一些细节。

f [ x ] [ 0 ] f[x][0] f[x][0]表示当 h [ f a x ] ≥ h [ x ] h[fa_x]≥h[x] h[fax]h[x]时以 x x x为根的子树的所有路径划分方案中 t t t值之和的最小值; f [ x ] [ 1 ] f[x][1] f[x][1]表示当 h [ f a x ] ≤ h [ x ] h[fa_x]≤h[x] h[fax]h[x]时以 x x x为根的子树的所有路径划分方案中 t t t值之和的最小值。

  • 对于叶子节点 x x x,显然对于其父节点 f a fa fa,如果 h [ f a ] ≥ h [ x ] h[fa]≥h[x] h[fa]h[x],则 f [ x ] [ 0 ] = t [ x ] f[x][0]=t[x] f[x][0]=t[x]否则 f [ x ] [ 0 ] = ∞ f[x][0]=\infin f[x][0]=;如果 h [ f a ] ≤ h [ x ] h[fa]≤h[x] h[fa]h[x],则 f [ x ] [ 1 ] = t [ x ] f[x][1]=t[x] f[x][1]=t[x]否则 f [ x ] [ 1 ] = ∞ f[x][1]=\infin f[x][1]=
  • 对于除叶子节点外的节点 x x x,讨论有多少个子节点 y y y满足 h [ x ] h[x] h[x]小于等于 h [ y ] h[y] h[y],记满足的数量为 i i i,子节点的数量为 n u m num num
    为了在数量为 i i i时确保子树的所有路径划分方案中 t t t值之和的最小值最小化,这里需要采取贪心策略:首先将子节点的 f [ y ] [ 0 ] f[y][0] f[y][0]求和得到 s u m sum sum,然后将 f [ y ] [ 1 ] − f [ y ] [ 0 ] f[y][1]-f[y][0] f[y][1]f[y][0]存放在数组 t m p tmp tmp中,那么 s u m sum sum加上数组中的 i i i个元素即为满足数量为 i i i的情况。显然选取数组中前 i i i小的数加在 s u m sum sum上得到的值最小。因此需要把 t m p tmp tmp从按升序排序。因为还有 i = 0 i=0 i=0的情况,因此令 t m p [ 0 ] = 0 tmp[0]=0 tmp[0]=0
    h [ f a ] ≥ h [ x ] h[fa]≥h[x] h[fa]h[x]。如果 i < n u m − i ii<numi x x x的子节点 y y y多数满足 h [ y ] ≤ h [ x ] h[y]≤h[x] h[y]h[x],因此为了使节点 x x x重复覆盖的次数最少,将其中 i i i对满足一条 h [ y ] ≤ h [ x ] h[y]≤h[x] h[y]h[x],另一条 h [ y ] ≥ h [ x ] h[y]≥h[x] h[y]h[x]的路径合为一条,使其共用一次节点 x x x,这样节点 x x x被覆盖了 i i i次,多余的路径其中一条与 x x x f a fa fa的路径共用一次 x x x,剩下的各覆盖 x x x节点一次,因此覆盖次数为 n u m − 2 i num-2i num2i。因此总的覆盖次数为 n u m − i num-i numi。如果 i ≥ n u m − i i≥num-i inumi那么成对结合形成的路径数量为 n u m − i num-i numi条,覆盖 x x x n u m − i num-i numi次,剩下的 2 i − n u m 2i-num 2inum条路径由于不能与 x x x f a fa fa的路径结合,因此加上 x x x f a fa fa的路径, x x x又被覆盖 2 i − n u m + 1 2i-num+1 2inum+1次。因此总覆盖次数为 i + 1 i+1 i+1次。但是如果 x x x为根节点,那么就不存在被 x x x到父节点的路径覆盖的情况,这样第二种情况还要再减 1 1 1
    由此的出 h [ f a ] ≥ h [ x ] h[fa]≥h[x] h[fa]h[x]时的状态转移方程为:
    f [ x ] [ 0 ] = { min ⁡ i = 0 n u m ( s u m + ∑ j = 0 i t m p [ j ] + t [ x ] ⋅ max ⁡ ( n u m − i , i + 1 ) )   i f ( x ≠ r o o t ) min ⁡ i = 0 n u m ( s u m + ∑ j = 0 i t m p [ j ] + t [ x ] ⋅ max ⁡ ( n u m − i , i ) )   i f ( x = r o o t ) f[x][0]=\left\{ \begin{aligned} &\min_{i=0}^{num}(sum+\sum_{j=0}^itmp[j]+t[x]·\max(num-i,i+1))\ if (x\not =root) \\ &\min_{i=0}^{num}(sum+\sum_{j=0}^itmp[j]+t[x]·\max(num-i,i))\ if (x =root)\\ \end{aligned} \right. f[x][0]=i=0minnum(sum+j=0itmp[j]+t[x]max(numi,i+1)) if(x=root)i=0minnum(sum+j=0itmp[j]+t[x]max(numi,i)) if(x=root)
    同理,若 h [ f a ] ≤ h [ x ] h[fa]≤h[x] h[fa]h[x],则转移方程为:
    f [ x ] [ 1 ] = { min ⁡ i = 0 n u m ( s u m + ∑ j = 0 i t m p [ j ] + t [ x ] ⋅ max ⁡ ( n u m − i + 1 , i ) )   i f ( x ≠ r o o t ) min ⁡ i = 0 n u m ( s u m + ∑ j = 0 i t m p [ j ] + t [ x ] ⋅ max ⁡ ( n u m − i , i ) )   i f ( x = r o o t ) f[x][1]=\left\{ \begin{aligned} &\min_{i=0}^{num}(sum+\sum_{j=0}^itmp[j]+t[x]·\max(num-i+1,i))\ if (x\not =root) \\ &\min_{i=0}^{num}(sum+\sum_{j=0}^itmp[j]+t[x]·\max(num-i,i))\ if (x =root)\\ \end{aligned} \right. f[x][1]=i=0minnum(sum+j=0itmp[j]+t[x]max(numi+1,i)) if(x=root)i=0minnum(sum+j=0itmp[j]+t[x]max(numi,i)) if(x=root)

复杂度为 O ( n log ⁡ n ) O(n\log n) O(nlogn)

#include

#define si(a) scanf("%d",&a)
#define sl(a) scanf("%lld",&a)
#define sd(a) scanf("%lf",&a)
#define sc(a) scahf("%c",&a);
#define ss(a) scanf("%s",a)
#define pi(a) printf("%d\n",a)
#define pl(a) printf("%lld\n",a)
#define pc(a) putchar(a)
#define ms(a) memset(a,0,sizeof(a))
#define repi(i, a, b) for(register int i=a;i<=b;++i)
#define repd(i, a, b) for(register int i=a;i>=b;--i)
#define reps(s) for(register int i=head[s];i;i=Next[i])
#define ll long long
#define ull unsigned long long
#define vi vector
#define pii pair
#define mii unordered_map
#define msi unordered_map
#define lowbit(x) ((x)&(-(x)))
#define ce(i, r) i==r?'\n':' '
#define pb push_back
#define fi first
#define se second
#define all(x) x.begin(),x.end()
#define INF 1e12
#define pr(x) cout<<#x<<": "<
using namespace std;

inline int qr() {
    int f = 0, fu = 1;
    char c = getchar();
    while (c < '0' || c > '9') {
        if (c == '-')fu = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9') {
        f = (f << 3) + (f << 1) + c - 48;
        c = getchar();
    }
    return f * fu;
}

const int N = 2e5 + 10;
int head[N], ver[N << 1], Next[N << 1], tot;
int t[N], h[N], n;
ll f[N][2];

inline void add(int x, int y) {
    ver[++tot] = y;
    Next[tot] = head[x];
    head[x] = tot;
}

void dp(int x, int fa) {
    bool up = h[fa] >= h[x] || x == 1;
    bool down = h[fa] <= h[x] || x == 1;
    vector<ll> tmp;
    tmp.pb(0);
    ll sum = 0;
    reps(x) {
        int y = ver[i];
        if (y == fa)continue;
        dp(y, x), sum += f[y][0], tmp.pb(f[y][1] - f[y][0]);
    }
    if (tmp.empty()) {
        f[x][0] = up ? t[x] : INF;
        f[x][1] = down ? t[x] : INF;
        return;
    }
    f[x][0] = f[x][1] = INF;
    sort(++tmp.begin(), tmp.end());
    int num = tmp.size();
    if (up) {
        ll res = sum;
        repi(i, 0, num - 1) {
            res += tmp[i];
            f[x][0] = min(f[x][0], res + 1ll * t[x] * max(num - i - 1, i + 1 - (x == 1)));
        }
    }
    if (down) {
        ll res = sum;
        repi(i, 0, num - 1) {
            res += tmp[i];
            f[x][1] = min(f[x][1], res + 1ll * t[x] * max(num - i - (x == 1), i));
        }
    }
}

int main() {
    n = qr();
    repi(i, 1, n)t[i] = qr();
    repi(i, 1, n)h[i] = qr();
    repi(i, 1, n - 1) {
        int x = qr(), y = qr();
        add(x, y), add(y, x);
    }
    dp(1, 0);
    pl(max(f[1][0], f[1][1]));
    return 0;
}

你可能感兴趣的:(ACM,树形dp,贪心)