CF437div D 贪心+并查集

来源:互联网 发布:toupview显微图像软件 编辑:程序博客网 时间:2024/06/01 19:50

题意:给出一个联通图 然后每一个节点有一个权值,然后我们需要做的是 是对于没两个点之间之间的所有简单路径而言 定义简单路径上面的点的最小值为这条简单路径的代价 而这些最小值中的最大值就是我们要求的这两点之间的函数值  最后我们需要给所有两点之间 函数值的均值

解法:这题和上两天网赛上的一题非常相似啊  但是又是那一题的加强版 首先点和边都是10w数量级的 也就是说我们是不能用dfs等的方法 然后考虑到正难则反 寻找点就是先建图 然后进行寻找一些点之间的权值 首先是要最小值 那么我们将所有的边按照从达到小排序 这样一来我们进行加点的时候更新出的值就一定是路径上的最小值了 然后考虑到要使所有的路径中的最大值 其实在路径合并的过程中也已经满足 那么我们只需要利用并查集构图就可以了

#include<cstdio>#include<iostream>#include<algorithm>using namespace std;#define maxn 111111int x,y,n,m,fa[maxn],sz[maxn];double val[maxn];int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}struct edge{    int l,r;double w;    bool operator<(const edge&x)const{        return w>x.w;    }}e[maxn];int main(){    scanf("%d%d",&n,&m);    for(int i=1;i<=n;++i){        scanf("%lf",&val[i]);fa[i]=i;sz[i]=1;    }    for(int i=0;i<m;++i){        scanf("%d%d",&x,&y);        e[i].l=x,e[i].r=y;        e[i].w=min(val[x],val[y]);    }    sort(e,e+m);    double s=0.0;    for(int i=0;i<m;++i){        x=find(e[i].l);y=find(e[i].r);        if(x!=y){            s+=e[i].w*sz[x]*sz[y];            sz[x]+=sz[y];fa[y]=x;        }    }    printf("%f\n",s*2/n/(n-1));    return 0;}


0 0
原创粉丝点击