CF437D The Child and Zoo

CF437D The Child and Zoo

题意

给定一个无向图,求所有点对间所有简单路径上最小点权的最大值的平均值。

思路

  1. 首先,我们可以将点权转移到边权上,边权为两端点点权的较小值。正确性显然。
  2. 然后,对于任意两个点之间的贡献,只有路径上含最大点权的简单路径有贡献,于是就可以把无向图转变为最大生成树。任意两个点间的贡献显然是在最大生成树上路径的最大边权。
  3. 考虑对于一条边的贡献,其实就是对于当前两端点连通块的大小相乘再乘该边边权。计算后合并两个连通块。

完了,一个最大生成树即可。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#include<cmath>
using namespace std;
inline int read(){
	int w=0,x=0;char c=getchar();
	while(!isdigit(c))w|=c=='-',c=getchar();
	while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
	return w?-x:x;
}
namespace star
{
	const int maxn=1e5+10;
	int n,m,siz[maxn],fa[maxn],a[maxn];
	double ans;
	struct edge{
		int u,v,d;
		inline bool operator < (const edge &zp) const{return d>zp.d;}
	}e[maxn];
	inline void onion(int x,int y,int k){
		if(siz[x]<siz[y])swap(x,y);
		ans+=1.0*siz[x]*siz[y]*k;
		fa[y]=x,siz[x]+=siz[y];
	}
	int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
	inline void work(){
		n=read(),m=read();
		for(int i=1;i<=n;i++) a[i]=read(),fa[i]=i,siz[i]=1;
		for(int u,v,i=1;i<=m;i++) u=read(),v=read(),e[i]=(edge){u,v,min(a[u],a[v])};
		sort(e+1,e+1+m);
		for(int cnt=0,i=1;i<=m and cnt<=n-1;i++){
			int u=find(e[i].u),v=find(e[i].v);
			if(u!=v)
				onion(u,v,e[i].d),cnt++;
		}
		printf("%.5lf\n",ans/n/(n-1)*2);
	}
}
signed main(){
	star::work();
	return 0;
}
posted @   Star_Cried  阅读(112)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示