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?
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, 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; }