zoukankan      html  css  js  c++  java
  • 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。

    #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
    ",x,fa,type,last_ans);
        //printf("x=%d,fa=%d : %lld %lld  value[%d]=%lld
    ",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
    ",first.first);
     
            if(q.size())
            {
                second=q.top();
              //  printf("%lld
    ",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
    ",sum);
                continue;
            }*/
     
            dfs(1,-1,0,LLONG_MIN/2);
            dfs(1,-1,1,LLONG_MAX/2);
     
            printf("%lld
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    高等代数中的名词解析No1
    概率论中的名词解释(个人理解,非官方) No1
    概率论中的公式解释(个人理解,非官方) No1
    CentOS7 网络设置
    神经网络与人工智能No0导言(笔记版)
    centos7 防火墙设置
    神经网络与人工智能No1Rosenblatt感知器(笔记版)
    输入法打不出来的数学符号大全
    php对xml文件的解析
    PHPExcel生成Excel模版
  • 原文地址:https://www.cnblogs.com/tian-luo/p/11371555.html
Copyright © 2011-2022 走看看