• 2019杭电多校 hdu6662 Acesrc and Travel (树形dp


    http://acm.hdu.edu.cn/showproblem.php?pid=6662

    题意:有两个人在树上博弈,每个点节点有两个分数a[i]和b[i],先手先选择一个点,后手在先手选的点的相邻点中选择一个点,然后先手在后手选的点的相邻点中选择一个两个人都没有走过的点,直到不能走,游戏就结束。一个人走到节点x,那么先手会获得分数a[x],后手就会会获得分数b[x]。最后询问先手能获得与后手的差值最大值。

    思路:先手固定好位置后,后手走。有两种走法,向下和向上。

    向下好办,用down[i][0]表示我从i走到i的儿子后所能得到的最大值,down[i][1]为对手走的最小值,那么down[i][0] = v[i]+max(down[son][1]), down[i][1]=v[i]+min(down[son][0])

    向上的话,走完后对面也分为向上或向下。

    向下走时,不能走当前上去的路,所以存每个点向下走的最值和次值,当最值和上去那条路得出的值相同,就换成次值。

    向上走时,从上到下一路维护即可。

      1 #include<bits/stdc++.h>
      2 #define ll long long 
      3 #define rep(i,a,b) for(int i=a;i<=b;i++)
      4 using namespace std;
      5 const int maxn = 1e5+5;
      6 const ll inf = 0x3f3f3f3f3f3f3f3f;
      7 ll a[maxn],b[maxn];
      8 int head[maxn],fa[maxn],to[maxn<<2],nex[maxn<<2],now;
      9 
     10 void add(int a,int b){
     11     nex[++now] = head[a];
     12     head[a] = now;
     13     to[now] = b;
     14 }
     15 
     16 ll down[maxn][2][2],up[maxn][2];
     17 bool lef[maxn];
     18 
     19 void dfs(int p){
     20     down[p][0][0] = down[p][0][1] = -inf;
     21     down[p][1][0] = down[p][1][1] = inf;
     22     lef[p] = 1;
     23     for(int i=head[p];i;i=nex[i]){
     24         if(to[i]==fa[p]) continue;
     25         lef[p] = 0;
     26         fa[to[i]] = p;
     27         dfs(to[i]);
     28         if(down[to[i]][1][0]+a[p]>=down[p][0][0]){
     29             down[p][0][1] = down[p][0][0];
     30             down[p][0][0] = down[to[i]][1][0]+a[p];
     31         }
     32         else if(down[to[i]][1][0]+a[p]>=down[p][0][1]){
     33             down[p][0][1] = down[to[i]][1][0]+a[p];
     34         }
     35         if(down[to[i]][0][0]+a[p]<=down[p][1][0]){
     36             down[p][1][1] = down[p][1][0];
     37             down[p][1][0] = down[to[i]][0][0]+a[p];
     38         }
     39         else if(down[to[i]][0][0]+a[p]<=down[p][1][1]){
     40             down[p][1][1] = down[to[i]][0][0]+a[p];
     41         }
     42     }
     43     if(lef[p]) down[p][0][0] = down[p][1][0] = a[p];
     44 }
     45 
     46 ll Abs(ll a){
     47     return a>0?a:-a;
     48 }
     49 
     50 void Dfs(int p){
     51     if(fa[p]==-1) up[p][0] = up[p][1] = inf;
     52     else {
     53         up[p][0] = inf;
     54         ll _down = down[fa[p]][1][0];
     55         if(_down==a[fa[p]]+down[p][0][0])
     56             _down = down[fa[p]][1][1];
     57         if(Abs(_down)!=inf)
     58             up[p][0] = min(up[p][0],a[p]+_down);
     59         if(fa[p]!=1)
     60             up[p][0] = min(up[p][0],a[p]+up[fa[p]][1]);
     61         if(up[p][0]==inf)
     62             up[p][0] = a[p]+a[fa[p]];
     63 
     64         up[p][1] = -inf;
     65         _down = down[fa[p]][0][0];
     66         if(_down==a[fa[p]]+down[p][1][0])
     67             _down=down[fa[p]][0][1];
     68         if(Abs(_down)!=inf)
     69             up[p][1]=max(up[p][1],a[p]+_down);
     70 
     71         if(fa[p]!=1)
     72             up[p][1]=max(up[p][1],a[p]+up[fa[p]][0]);
     73 
     74         if(up[p][1]==-inf)
     75             up[p][1]=a[p]+a[fa[p]];
     76     }
     77     for(int i=head[p];i;i=nex[i]){
     78         if(to[i]==fa[p])continue;
     79         Dfs(to[i]);
     80     }
     81 }
     82 
     83 
     84 
     85 int main(){
     86     ios::sync_with_stdio(0);
     87     cin.tie(0);
     88     cout.tie(0);
     89     int t;
     90     cin>>t;
     91     while(t--){
     92         memset(head,0,sizeof head);
     93         now = 0;
     94         int n;
     95         cin>>n;
     96         rep(i,1,n) cin>>a[i];
     97         rep(i,1,n) cin>>b[i], a[i]-=b[i];
     98         rep(i,1,n-1){
     99             int u,v;
    100             cin>>u>>v;
    101             add(u,v);
    102             add(v,u);
    103         }
    104         if(n==1){
    105             cout<<a[1]<<endl;
    106             continue;
    107         }
    108         fa[1] = -1;
    109         dfs(1);
    110         Dfs(1);
    111         ll ans = -inf;
    112         for(int i=1;i<=n;i++){
    113             ll res = inf;
    114             if(!lef[i]) res = min(res,down[i][1][0]);
    115             if(i!=1) res = min(res,up[i][1]);
    116             ans = max(ans,res);
    117         }
    118         cout<<ans<<endl;
    119     }
    120     return 0;
    121 }
    View Code
  • 相关阅读:
    调试 XPTable
    适合IT经理的编程语言
    请问我如何在一个webBrowser控件中加载一个 html格式的字符串 _NET技术 C#
    DotNetBar 教程
    思梅
    无家可归的苦
    思霞
    思兰
    十大因素——造就优秀的董事长
    思萍
  • 原文地址:https://www.cnblogs.com/wzgg/p/11377145.html
Copyright © 2020-2023  润新知