题目链接:点这里!!!!!
题解:dp(i,u)表示第i个人选第u个显示器为根的子树得到的最大值。然后去枚举i和他二子的最大值和最小值就可以了。
时间复杂度为O(n^3)
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<sstream>
#include<algorithm>
#include<vector>
#include<bitset>
#include<set>
#include<queue>
#include<stack>
#include<map>
#include<cstdlib>
#include<cmath>
#define LL long long
#define pb push_back
#define pa pair<int,int>
#define clr(a,b) memset(a,b,sizeof(a))
#define lson lr<<1,l,mid
#define rson lr<<1|1,mid+1,r
#define bug(x) printf("%d++++++++++++++++++++%d\n",x,x)
#define key_value ch[ch[root][1]][0]
#pragma comment(linker, "/STACK:102400000000,102400000000")
const LL MOD = 1000000007;
const int N = 100+15;
const int maxn = 8e3+15;
const int letter = 130;
const LL INF = 1e18;
const double pi=acos(-1.0);
const double eps=1e-10;
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int n;
LL p[N][2],dp[N][2];
int vis[N];
vector<int>G[N],g[N];
stack<int>s;
queue<int>q;
void bfs(int y){
while(!q.empty()) q.pop();
while(!s.empty()) s.pop();
q.push(y);
vis[y]=1;
while(!q.empty()){
int x=q.front();
q.pop();
s.push(x);
for(int i=0;i<G[x].size();i++){
int to=G[x][i];
if(!vis[to]){
g[x].pb(to);
vis[to]=1;
q.push(to);
}
}
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%lld%lld",&p[i][0],&p[i][1]);
if(p[i][0]>p[i][1]) swap(p[i][0],p[i][1]);
}
for(int i=1;i<=n;i++)G[i].clear();
int x,y;
for(int i=0;i<n-1;i++){
scanf("%d%d",&x,&y);
G[x].pb(y),G[y].pb(x);
}
bfs(1);
LL max1=0,min1=0;
int c,d,e;
while(!s.empty()){
x=s.top(),s.pop();
if(g[x].size()==0){
dp[x][0]=p[x][0];
dp[x][1]=p[x][1];
}
else if(g[x].size()==1){
y=g[x][0];
for(int pd=0;pd<2;pd++){
max1=max(p[x][pd],p[y][0]);
min1=min(p[x][pd],p[y][0]);
LL p0=(max1-min1+999)/1000*666*x;
max1=max(p[x][pd],p[y][1]);
min1=min(p[x][pd],p[y][1]);
LL p1=(max1-min1+999)/1000*666*x;
if(dp[y][0]-p0>dp[y][1]-p1) dp[x][pd]=dp[y][0]-p0+p[x][pd];
else dp[x][pd]=dp[y][1]-p1+p[x][pd];
}
}
else {
dp[x][0]=dp[x][1]=-INF;
for(int pd=0;pd<2;pd++){
for(int u=0;u<2;u++)
for(int i=0;i<g[x].size();i++)
for(int v=0;v<2;v++)
for(int j=0;j<g[x].size();j++){
if(i==j) continue;
c=g[x][i],d=g[x][j];
LL max1=max(p[c][u],p[d][v]);
LL min1=min(p[c][u],p[d][v]);
if(p[x][pd]<min1||p[x][pd]>max1) continue;
LL ans=0;
ans=ans+dp[c][u]+dp[d][v];
ans=ans-(max1-min1+999)/1000*666*x;
int flag=1;
for(int k=0;k<g[x].size();k++){
LL vs=-INF;
if(i==k||j==k)continue;
e=g[x][k];
if(p[e][1]<min1||p[e][0]>max1||(p[e][0]<min1&&p[e][1]>max1)){flag=0;break;}
if(min1<=p[e][0]&&p[e][0]<=max1) vs=dp[e][0];
if(min1<=p[e][1]&&p[e][1]<=max1) vs=max(vs,dp[e][1]);
ans+=vs;
}
if(!flag) continue;
dp[x][pd]=max(dp[x][pd],ans+p[x][pd]);
}
}
for(int pd=0;pd<2;pd++){
for(int u=0;u<2;u++)
for(int i=0;i<g[x].size();i++){
c=g[x][i];
LL max1=max(p[c][u],p[x][pd]);
LL min1=min(p[c][u],p[x][pd]);
LL ans=dp[c][u];
ans=ans-(max1-min1+999)/1000*666*x;
int flag=1;
for(int k=0;k<g[x].size();k++){
LL vs=-INF;
if(i==k)continue;
e=g[x][k];
if(p[e][1]<min1||p[e][0]>max1||(p[e][0]<min1&&p[e][1]>max1)){flag=0;break;}
if(min1<=p[e][0]&&p[e][0]<=max1) vs=dp[e][0];
if(min1<=p[e][1]&&p[e][1]<=max1) vs=max(vs,dp[e][1]);
ans+=vs;
}
if(!flag) continue;
dp[x][pd]=max(dp[x][pd],ans+p[x][pd]);
}
}
}
}
printf("%lld\n",max(dp[1][0],dp[1][1]));
return 0;
}