Acesrc and Travel
Acesrc and Travel
时间限制: 1 Sec 内存限制: 128 MB
题目描述
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?
输入
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.
输出
样例输入
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+;
struct ss
{
int u,v,next;
};
ss edg[N*];
int head[N],sum_edge=; 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=;
long long dp[N][]; void init(int n)
{
for(int i=;i<=n;i++)
{
head[i]=-;
dp[i][]=dp[i][]=;
}
sum_edge=;
ans=LLONG_MIN;
} long long dfs1(int x,int fa,int type)
{
if(dp[x][type])return dp[x][type];
long long now= (type== ? LLONG_MIN : LLONG_MAX); for(int i=head[x];i!=-;i=edg[i].next)
{
int v=edg[i].v;
if(v==fa)continue; if(type==)now=max(now,dfs1(v,x,)+value[x]);
else
now=min(now,dfs1(v,x,)+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!=-;i=edg[i].next)
{
int v=edg[i].v;
if(v==fa)continue; if(type==)q.push(make_pair(-dfs1(v,x,),v));
else
q.push(make_pair(dfs1(v,x,),v)); if(q.size()>)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!=)first=make_pair(LLONG_MAX/,-);
else
first=make_pair(,-);
}
}
else
{
if(x!=)second=make_pair(LLONG_MAX/,-);
else
second=make_pair(,-);
} if(type==)
{
for(int i=head[x];i!=-;i=edg[i].next)
{
int v=edg[i].v;
if(v==fa)continue; if(v==second.second)dfs(v,x,,max(last_ans,-first.first)+value[x]);
else
dfs(v,x,,max(last_ans,-second.first)+value[x]);
}
}
else
{
ans=max(ans,min(last_ans,second.first)+value[x]);
for(int i=head[x];i!=-;i=edg[i].next)
{
int v=edg[i].v;
if(v==fa)continue; if(v==second.second)dfs(v,x,,min(last_ans,first.first)+value[x]);
else
dfs(v,x,,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=;i<=n;i++)
scanf("%lld",&value[i]); for(int i=;i<=n;i++)
{
long long a;
scanf("%lld",&a);
value[i]-=a;
} for(int i=;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(,-,,LLONG_MIN/);
dfs(,-,,LLONG_MAX/); printf("%lld\n",ans);
}
return ;
}
Acesrc and Travel的更多相关文章
- HDU 6662 Acesrc and Travel (换根dp)
Problem Description Acesrc is a famous tourist at Nanjing University second to none. During this sum ...
- 2019杭电多校 hdu6662 Acesrc and Travel (树形dp
http://acm.hdu.edu.cn/showproblem.php?pid=6662 题意:有两个人在树上博弈,每个点节点有两个分数a[i]和b[i],先手先选择一个点,后手在先手选的点的相邻 ...
- Acesrc and Travel(2019年杭电多校第八场06+HDU6662+换根dp)
题目链接 传送门 题意 两个绝顶聪明的人在树上玩博弈,规则是轮流选择下一个要到达的点,每达到一个点时,先手和后手分别获得\(a_i,b_i\)(到达这个点时两个人都会获得)的权值,已经经过的点无法再次 ...
- HDU 6662 Acesrc and Travel 换根DP,宇宙最傻记录
#include<bits/stdc++.h> typedef long long ll; using namespace std; const int maxn=1e6+50; cons ...
- 2019 Multi-University Training Contest 8 - 1006 - Acesrc and Travel - 树形dp
http://acm.hdu.edu.cn/showproblem.php?pid=6662 仿照 CC B - TREE 那道题的思路写的,差不多.也是要走路径. 像这两种必须走到叶子的路径感觉是必 ...
- 【HDOJ6662】Acesrc and Travel(树形DP,换根)
题意:有一棵n个点的树,每个点上有两个值a[i],b[i] A和B在树上行动,A到达i能得到a[i]的偷税值,B能得到b[i],每次行动只能选择相邻的点作为目标 两个人都想最大化自己的偷税值和对方的差 ...
- 【HDU6662】Acesrc and Travel【树形DP】
题目大意:给你一棵树,每个节点有一个权值,Alice和Bob进行博弈,起点由Alice确定,确定后交替选择下一个点,Alice目标是最终值尽可能大,Bob目标是尽可能小 题解:很明显是树形DP,那么考 ...
- 【HDU6662】Acesrc and Travel(树型Dp)
题目链接 大意 给出一颗树,每个点上有一个权值\(A[i]\),有两个绝顶聪明的人甲和乙. 甲乙两人一起在树上轮流走,不能走之前经过的点.(甲乙时刻在一起) 甲先手,并可以确定起点.甲想要走过的点权之 ...
- 2019DX#8
Solved Pro.ID Title Ratio(Accepted / Submitted) 1001 Acesrc and Cube Hypernet 7.32%(3/41) 1002 A ...
随机推荐
- 03_mybatis配置文件详解
1. SqlMapConfig.xml mybatis全局配置文件SqlMapConfig.xml,配置内容如下: *properties(属性) setting(全局配置参数) typeAliase ...
- vue 返回上一页
参考:https://www.cnblogs.com/chenguiya/p/9118265.html 注:需为history模式 方法一: @click="back" back( ...
- 2019-7-1-Roslyn-让编译时候-Message-内容默认输出
title author date CreateTime categories Roslyn 让编译时候 Message 内容默认输出 lindexi 2019-07-01 14:16:59 +080 ...
- Swimming Balls
Swimming Balls https://vjudge.net/contest/318752#problem/J如果直接算,各种球的情况都不清楚,因为放一个球之后,水位的变化也会影响之前放入的球, ...
- leetcode-80-删除排序数组中的重复项②
题目描述: 第一次提交: class Solution: def removeDuplicates(self, nums: List[int]) -> int: nums.reverse() f ...
- 【转载】objective-c强引用与弱引用
形象比喻蛮好玩的^_^ __weak 和 __strong 会出现在声明中 默认情况下,一个指针都会使用 __strong 属性,表明这是一个强引用.这意味着,只要引用存在,对象就不能被销毁 ...
- Django常用组件之分页器
目录 循环插入数据测试 实现分页器 视图层使用 模板层使用 循环插入数据测试 # ORM 帮我们提供了循环插入数据更快捷的方法: book_list = [] for i in range(1000) ...
- vue 自定义指令input表单的数据验证
一.代码 <template> <div class="check" > <h3>{{msg}}</h3> <div clas ...
- iOS之CGAffineTransform属性详解和方法使用
1.CGAffineTransform简介 UIView有个属性transform,是CGAffineTransform类型.可以使其在二维界面做旋转.平移.缩放单独或者组合动画! CGAffineT ...
- mongdb 使用聚合函数异常
异常信息: Command execution failed: Error [The 'cursor' option is required, except for aggregate with t ...