6364. [2019.9.20] horse simulation NOIP2019

Title Description




answer

One kindClearWater Method: max (0, - (right dot - Right side and * 2))

Because it will hang in the middle of the physical value may be smaller, so consider seeking to finish each of them at least a physical value required subtree


From the sub-tree inquire up the answer of the current point

Meike set up sub-tree away from the root down to the required physical value f, go through contributions to the sum

Due to the current point to add -> son this edge, so actually finish the contribution sum '= sum- right side * 2

Desired physical value f '= max (edge ​​weights + f, 2 * right side -sum), in fact, there are two cases where

① current point -> son -> subtree (-> son), it is the worst case (worst case subtree + right side)

② current point -> son -> sub-tree -> son -> current point, the final contribution actually sum- right side * 2, then you need at least max (0, right side * 2-sum) of physical strength


Obviously for point contribution ≥0 in accordance with the needs of small to large to take

Contribution <0 point, the definition of a reduced amount = - Contribution

Well, according to demand - reducing the amount of descending sort can

prove:

Defined difference = demand - the amount of reduction

For the two sons, and reducing the amount of the difference is provided for the first son of a and B, respectively, for the second cd

Assume has been sorted in accordance with the difference, and after ordering the adjacent two sons, then there a≥c

After the exchange will not prove better

Let x go before these two physical sub-tree, to ensure that no negative numbers in the middle and can achieve demand

Then there

Before the exchange:

x≥a+b,x-b≥c+d

After the exchange:

x≥c+d,x-d≥a+b

According to equation

+ Contribution to the root of physical recovery - Meike sub-tree and reduce the amount of residual strength =, which only restore physical strength is variable, so the rest can be found in the less physically smaller answer =

Since the remaining strength before and after the exchange are xbd, so to make x as small as possible (too much could lead to a surplus)

They became proof

max(a+b,b+c+d)≤max(c+d,a+b+d)

Since a + b + d≤max (c + d, a + b + d), and a + b + d≥a + b and b + c + d (a≥c), so that max (a + b, b + c + d) ≤a + b + d≤max (c + d, a + b + d)

Is proved

code

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
using namespace std;

struct type{
    long long f,sum;
} b[100001],c[100001];
int a[200001][3];
int ls[100001];
int w[100001];
long long f[100001];
long long sum[100001];
int n,i,j,k,l,len;
long long ans;

bool cmp(type a,type b)
{
    return a.f<b.f;
}
bool Cmp(type a,type b)
{
    return a.f-a.sum>b.f-b.sum;
}

void New(int x,int y,int z)
{
    ++len;
    a[len][0]=y;
    a[len][1]=ls[x];
    a[len][2]=z;
    ls[x]=len;
}

void dfs(int Fa,int t)
{
    int i,l1=0,l2=0;
    long long now=w[t];
    
    sum[t]=w[t];
    
    for (i=ls[t]; i; i=a[i][1])
    if (a[i][0]!=Fa)
    {
        dfs(t,a[i][0]);
        sum[t]+=sum[a[i][0]]-a[i][2]-a[i][2];
    }
    
    if (!ls[t]) return;
    
    for (i=ls[t]; i; i=a[i][1])
    if (a[i][0]!=Fa)
    {
        if (sum[a[i][0]]-a[i][2]-a[i][2]>=0)
        {
            ++l1;
            b[l1].f=max(f[a[i][0]]+a[i][2],-(sum[a[i][0]]-a[i][2]-a[i][2]));
            b[l1].sum=sum[a[i][0]]-a[i][2]-a[i][2];
        }
        else
        {
            ++l2;
            c[l2].f=max(f[a[i][0]]+a[i][2],-(sum[a[i][0]]-a[i][2]-a[i][2]));
            c[l2].sum=-(sum[a[i][0]]-a[i][2]-a[i][2]);
        }
    }
    
    if (l1)
    {
        sort(b+1,b+l1+1,cmp);
        fo(i,1,l1)
        {
            if (now<b[i].f)
            {
                f[t]+=b[i].f-now;
                now=b[i].f;
            }
            now+=b[i].sum;
        }
    }
    if (l2)
    {
        sort(c+1,c+l2+1,Cmp);
        if (now<(c[1].f-c[1].sum))
        {
            f[t]+=(c[1].f-c[1].sum)-now;
            now=0;
        }
        else
        now-=(c[1].f-c[1].sum);
        
        fo(i,1,l2)
        {
            if (i>1)
            now+=(c[i-1].f-c[i-1].sum)-(c[i].f-c[i].sum);
            
            if (now<c[i].sum)
            {
                f[t]+=c[i].sum-now;
                now=c[i].sum;
            }
            now-=c[i].sum;
        }
    }
}

int main()
{
//  freopen("a.in","r",stdin);
//  freopen("b.out","w",stdout);
    freopen("horse.in","r",stdin);
    freopen("horse.out","w",stdout);
    
    scanf("%d",&n);
    fo(i,1,n)
    scanf("%d",&w[i]);
    fo(i,2,n)
    {
        scanf("%d%d%d",&j,&k,&l);
        
        New(j,k,l);
        New(k,j,l);
    }
    
    dfs(0,1);
    
    printf("%lld\n",f[1]);
    
    fclose(stdin);
    fclose(stdout);
    
    return 0;
}

Guess you like

Origin www.cnblogs.com/gmh77/p/11567372.html