• 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
    ",ans/n/(n-1)*2);
    	}
    }
    signed main(){
    	star::work();
    	return 0;
    }
    
  • 相关阅读:
    Linux 套接字编程
    Linux 网络(连接)相关参数作用
    Python WSGI
    Ubuntu Cloud Image in Openstack
    AWK
    MySQL--开发技巧(一)
    spring MVC--配置注解
    javascript-JQuery样式篇(一)
    JSP--常用标签
    spring MVC basic
  • 原文地址:https://www.cnblogs.com/BrotherHood/p/13904663.html
Copyright © 2020-2023  润新知