Acesrc and Travel

 Acesrc and Travel

時間限制: 1 Sec  內存限制: 128 MB

題目描述

Acesrc is a famous tourist at Nanjing University second to none. During this summer holiday, he, along with Zhang and Liu, is going to travel to Hong Kong. There are n spots in Hong Kong, and n−1 bidirectional sightseeing bus routes connecting these spots. They decide to visit some spots by bus.

However, Zhang and Liu have different preferences for these spots. They respectively set a satisfactory value for each spot. If they visit the ith spot, Zhang will obtain satisfactory value ai, and Liu will obtain bi. Starting with Zhang, they alternately decide the next spot to visit for the sake of fairness. There must be a bus route between the current spot and the next spot to visit. Moreover, they would never like to visit a spot twice. If anyone can't find such a next spot to visit, they have no choice but to end this travel.

Zhang and Liu are both super smart competitive programmers. Either want to maximize the difference between his total satisfactory value and the other's. Now Acesrc wonders, if they both choose optimally, what is the difference between total satisfactory values of Zhang and Liu?

輸入

The first line of input consists of a single integer T (1≤T≤30), denoting the number of test cases.

For each test case, the first line contains a single integer n (1≤n≤105), denoting the number of spots. Each of the next two lines contains n integers, a1,a2,⋯,an and b1,b2,⋯,bn (0≤ai,bi≤109), denoting the 
satisfactory value of Zhang and Liu for every spot, respectively. Each of the last n−1 lines contains two integers x,y (1≤x,y≤n,x≠y), denoting a bus route between the xth spot and the yth spot. It is reachable from any spot to any other spot through these bus routes.

It is guaranteed that the sum of n does not exceed 5.01×105.

輸出

For each test case, print a single integer in one line, the difference of total satisfactory values if they both choose optimally.

樣例輸入

1
3
1 1 1
0 2 3
1 2
1 3

樣例輸出

-1

題意:有兩我的輪流在一棵樹上選擇點,每一個點有一個權值,A想讓權值和最大,B想讓權值和最小,下一次選擇的點必須和此次選擇的點有直接邊鏈接,且點不能重複選擇,A能夠選擇任意一個點做爲初始點,問最後權值和是多少。
思路:考慮DP,但這是一個無根樹,因而首先要轉化成有根樹DP,即首先把1號點做爲根節點,而後DP算出:A或者B選擇了某一個點,且上一步是從改點的父親走過來的最優權值和。而後再考慮父親反向邊的DP,即計算出:A或者B選擇了某一個點,且下一步是到改點的父親的最優權值和。則答案就是在全部B選擇點時,維護最大值。
總結:無根樹DP就是有根樹DP加上父親反向邊的DP。c++

#pragma GCC optimize(3,"Ofast","inline")
#include <bits/stdc++.h>
using namespace std;
 
const int N = 6e5+50;
struct ss
{
    int u,v,next;
};
ss edg[N*2];
int head[N],sum_edge=0;
 
void addedge(int u,int v)
{
    edg[sum_edge]=(ss){u,v,head[u]};
    head[u]=sum_edge++;
}
 
long long value[N];
long long ans=0;
long long dp[N][2];
 
 
void init(int n)
{
    for(int i=0;i<=n;i++)
    {
        head[i]=-1;
        dp[i][0]=dp[i][1]=0;
    }
    sum_edge=0;
    ans=LLONG_MIN;
}
 
long long dfs1(int x,int fa,int type)
{
    if(dp[x][type])return dp[x][type];
    long long now= (type==0 ? LLONG_MIN : LLONG_MAX);
 
    for(int i=head[x];i!=-1;i=edg[i].next)
    {
        int v=edg[i].v;
        if(v==fa)continue;
 
        if(type==0)now=max(now,dfs1(v,x,1)+value[x]);
        else
            now=min(now,dfs1(v,x,0)+value[x]);
    }
    return dp[x][type]=((now==LLONG_MAX||now==LLONG_MIN) ? value[x] : now);
}
 
long long dfs(int x,int fa,int type,long long last_ans)
{
   // printf("%d %d %d %lld\n",x,fa,type,last_ans);
    //printf("x=%d,fa=%d : %lld %lld  value[%d]=%lld\n",x,fa,dfs1(x,fa,0),dfs1(x,fa,1),x,value[x]);
    priority_queue<pair<long long,int> >q;
    for(int i=head[x];i!=-1;i=edg[i].next)
    {
        int v=edg[i].v;
        if(v==fa)continue;
 
        if(type==0)q.push(make_pair(-dfs1(v,x,1),v));
        else
            q.push(make_pair(dfs1(v,x,0),v));
 
        if(q.size()>2)q.pop();
    }
 
    pair<long long,int> first;
    pair<long long,int> second;
 
    if(q.size())
    {
       first=q.top();
       q.pop();
      // printf("%lld\n",first.first);
 
        if(q.size())
        {
            second=q.top();
          //  printf("%lld\n",second.first);
            q.pop();
        }
        else
        {
            second=first;
 
            if(x!=1)first=make_pair(LLONG_MAX/2,-1);
            else
                first=make_pair(0,-1);
        }
    }
    else
    {
        if(x!=1)second=make_pair(LLONG_MAX/2,-1);
        else
            second=make_pair(0,-1);
    }
 
    if(type==0)
    {
        for(int i=head[x];i!=-1;i=edg[i].next)
        {
            int v=edg[i].v;
            if(v==fa)continue;
 
            if(v==second.second)dfs(v,x,1,max(last_ans,-first.first)+value[x]);
            else
                dfs(v,x,1,max(last_ans,-second.first)+value[x]);
        }
    }
    else
    {
        ans=max(ans,min(last_ans,second.first)+value[x]);
        for(int i=head[x];i!=-1;i=edg[i].next)
        {
            int v=edg[i].v;
            if(v==fa)continue;
 
            if(v==second.second)dfs(v,x,0,min(last_ans,first.first)+value[x]);
            else
                dfs(v,x,0,min(last_ans,second.first)+value[x]);
        }
    }
}
 
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        scanf("%d",&n);
        init(n);
 
        for(int i=1;i<=n;i++)
        scanf("%lld",&value[i]);
 
        for(int i=1;i<=n;i++)
        {
            long long a;
            scanf("%lld",&a);
            value[i]-=a;
        }
 
        for(int i=1;i<n;i++)
        {
            int u,v;
            scanf("%d %d",&u,&v);
            addedge(u,v);
            addedge(v,u);
        }
 
     /*   if(n<=2)
        {
            long long sum=0;
            for(int i=1;i<=n;i++)sum+=value[i];
            printf("%lld\n",sum);
            continue;
        }*/
 
        dfs(1,-1,0,LLONG_MIN/2);
        dfs(1,-1,1,LLONG_MAX/2);
 
        printf("%lld\n",ans);
    }
    return 0;
}
View Code
相關文章
相關標籤/搜索