题目链接:登录—专业IT笔试面试备考平台_牛客网
输入:
2
3 2
1 2
输出:
1.562500
题意:有一棵有n个结点的树,每个结点对应着一个点权b,然后让我们求一条简单路径,使得上述式子的值最大。
对上面的式子化简得-x^2+(),这个式子很容易得到最大值就是
,所以就相当于我们要求得一条简单路径使得这条简单路径上的点的点权平均值的绝对值最大。
先说一个结论:点权平均值最大的简单路径含有的点数不会大于3。
同理可以得到点权平均值最小的简单路径含有的点数也不会大于3。
下面证明平均值最大的情况(平均值最小的情况类似)
证明:我们假设一个简单路径含有的点数为m(m>3),点权平均值为x,那么我们可以将这个简单路径分为一段含有n-2个点的简单路径,而另一个简单路径只有2个点,那么这两段简单路径的点权平均值至少有一段是不小于x的,这是显然的,如果是含有n-2个点的简单路径的点权平均值不小于x,那么我们可以用类似的方法继续分,直到简单路径含有的点数小于等于3为止,而如果是含有2个点的简单路径的点权平均值更大,那么我们就不必再分了,已经有一段简单路径的点权平均值大于等于原简单路径的点权平均值且含有的点数不大于3了,到这这个结论就证明完毕了,这个结论还是蛮新颖的,这就可以类比到连续一段数求最大平均值,那么最大平均值一定可以由连续的两个数或者连续的三个数得到。
所以对于这道题,符合题目要求的简单路径可能是两个连续的点构成的,也可能是下面两种由3个连续的点组成的:
这两种情况都不是特别难求,直接一次搜索就可以求得答案。
下面附上代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#include<cmath>
using namespace std;
const int N=5e5+10;
int h[N],ne[N],e[N],idx,w[N];
double ans;
void add(int x,int y)
{
e[idx]=y;
ne[idx]=h[x];
h[x]=idx++;
}
void dfs(int x,int fa)
{
vector<int>a;
for(int i=h[x];i!=-1;i=ne[i])
{
int j=e[i];
if(j==fa) continue;
ans=max(ans,abs(w[fa]+w[x]+w[j])/3.0);
dfs(j,x);
a.push_back(w[j]);
}
if(a.size()<2) return ;
sort(a.begin(),a.end());
ans=max(ans,abs(w[x]+a[0]+a[1])/3.0);
ans=max(ans,abs(w[x]+a[a.size()-1]+a[a.size()-2])/3.0);
}
int main()
{
int n;
cin>>n;
memset(h,-1,sizeof h);
for(int i=1;i<=n;i++)
scanf("%d",&w[i]);
int u,v;
for(int i=1;i<n;i++)
{
scanf("%d%d",&u,&v);
add(u,v);add(v,u);
ans=max(ans,abs(w[u]+w[v])/2.0);
}
dfs(1,0);
printf("%.7lf\n",ans*ans/4);
return 0;
}