打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
清北学堂NOIP训练营内部试题!


解析在代码后面

代码

#include

#include

#define N 20001

#define M 100001

using namespace std;

typedef long long LL;

int fa[N],siz[N];

struct node

{

    int u,v,w;

}e[M];

bool cmp(node p,node q)

{

    return p.w<>

}

int find(int i) { return fa[i]==i ? i : fa[i]=find(fa[i]); }

int main()

{

    freopen('detective.in','r',stdin);

    freopen('detective.out','w',stdout);

    int n,m;

    scanf('%d%d',&n,&m);

    for(int i=1;i<=m;i++)>

    sort(e+1,e+m+1,cmp);

    for(int i=1;i<=n;i++) fa[i]="">

    int u,v;

    LL sum=0,cnt=0;

    for(int i=1;i<>

    {

        u=find(e[i].u); v=find(e[i].v);

        if(u==v) continue;

        sum+=e[i].w;

        cnt+=1ll*siz[u]*siz[v]*e[i].w;

        fa[v]=u; siz[u]+=siz[v];

    }

    printf('%.2lf',sum-cnt*2.0/(n*(n-1)));

}

解析:

60分做法:

先做一遍最小生成树

枚举两个点i,j,那么替换掉的是最小生成树上i,j路径上权值最大的边

倍增维护

时间复杂度:O(n*n*logn)

 

100分做法:

换一个角度,考虑被替换掉的边的贡献

边e要想被替换掉,那么点 i,j 要满足两个条件:

① 设e的两端点为u,v,i∈u,j∈v

② e的边权是连通 i,j 必经之路(最短路)上边权最大的边

怎么找这条边?——Kruscal算法

Kruscal算法每次找还没有加进去的权值最小的边,所以满足必经之路

还没有加进去的边权最小的边,是已加进去的边权最大的边,所以满足路径上边权最大

所以,设最小生成树的总权值为sum,设当前边权为w,当前边连接的两点的集合大小分别为 s1、s2

ans=(sum*n*(n-1)- 2*Σ s1*s2*w)/(n*(n-1))

n*(n-1):任意选两个点共有这些选法

Σ 前乘2:u,v 和 v,u 算不同的方案


本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
运输计划[二分答案 LCA 树上差分]
AGC052 B - Tree Edges XOR Editorial
树链剖分详解及模板
算法分析第一次作业
「SOL」星际迷航(LOJ)
8.2镖局运镖-------图的最小生成树 无向图 有权重 Prim算法
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服