Find the Maximum
题链
整理题意发现就是找一个连通块 然后让他的平均绝对值最大
平时的背包都是n2的 显然不能做了
我们考虑猜一些结论
当时我想的就是可能最多不会很多点
比如我们要是次大与最大挨着显然很好
要是离一个点比如 10 1 10 我们拿着显然也很好
要是离两个点比如 10 1 1 10这样显然不如就拿一般好算一点
我们继续想要延长这个比如先是一个大的比如 1e10 0 后面我们得让他吃到好处
就必须大于1e5
1e10 0 1e5+1 1e5+1 我们发现这样就都选下界我们都是只要右边两个就可以了
我们猜测就只有2 3个点再连通块里就可以了
然后对每个点分类讨论一下就可以了
int n,w[N];
double ans=-2e9,res=2e9;
vector<int>g[N];
void dfs(int u,int fa){
vector<int>a;
for(auto v:g[u]){
if(v==fa)continue;
dfs(v,u);
a.push_back(w[v]);
}
sort(all(a),greater<>());
int mx1,mx2,mn1,mn2;
if(a.size())mx1=a[0],mn1=a.back();
if(a.size()>=2)mx2=a[1],mn2=a[a.size()-2];
if(a.size()>=2)ans=max(ans,(double)(mx1+w[u]+mx2)/3);
if(a.size()&&fa)ans=max(ans,(double)(w[fa]+w[u]+mx1)/3);
if(a.size())ans=max(ans,(double)(w[u]+mx1)/2);
if(a.size()>=2)res=min(res,(double)(mn1+w[u]+mn2)/3);
if(a.size()&&fa)res=min(res,(double)(w[fa]+w[u]+mn1)/3);
if(a.size())res=min(res,(double)(w[u]+mn1)/2);
}
void solve(){
cin>>n;
for(int i=1;i<=n;i++)cin>>w[i];
for(int i=1;i<n;i++){
int u,v;cin>>u>>v;
g[u].push_back(v);
g[v].push_back(u);
}
dfs(1,0);
printf("%.8lf",max(ans*ans,res*res)/4);
}
标签:int,double,ans,fa,2021,res,昆明,size
From: https://www.cnblogs.com/ycllz/p/16939512.html