题意:求最小生成树,和任意两个点之间距离的期望
官方题解:
最后求两遍点的积的时候,还是要判断父子关系。
注意 long long
#include <bits/stdc++.h> using namespace std; typedef long long LL; const int maxn = 100000+5; int father[maxn]; int Find_Set(int x) { if(x!=father[x]) father[x] = Find_Set(father[x]); return father[x]; } struct Edge { int u,v,d; bool operator < (const Edge & rhs) const { return d < rhs.d; } }edges[1000000+5]; struct o { int v,d; }; vector <o> G[maxn]; int sum[maxn]; bool vis[maxn]; int ff[maxn]; int x; void dfs(int r,int f) { if(vis[r]) return ; sum[r] = 1; vis[r] = true; for(int i=0;i<G[r].size();i++) { int v = G[r][i].v; if(v!=f) { ff[v] = r; dfs(v,r); sum[r] +=sum[v]; } } } vector<Edge> minans; int main() { //freopen("in.txt","r",stdin); int t; scanf("%d",&t); while(t--) { int n,m; scanf("%d%d",&n,&m); for(int i=0;i<=n;i++) father[i] = i; for(int i=0;i<=n;i++) { G[i].clear(); } minans.clear(); memset(sum,0,sizeof(sum)); memset(vis,0,sizeof(vis)); x = 0; for(int i=0;i<m;i++) scanf("%d%d%d",&edges[i].u,&edges[i].v,&edges[i].d); sort(edges,edges+m); LL ans = 0; for(int i=0;i<m;i++) { int u = edges[i].u; int v = edges[i].v; int d = edges[i].d; int fx = Find_Set(u); int fy = Find_Set(v); if(fx!=fy) { G[u].push_back((o){v,edges[i].d}); G[v].push_back((o){u,edges[i].d}); minans.push_back((Edge){u,v,d}); father[fy] = fx; ans +=edges[i].d; } } dfs(1,-1); LL x = 0; for(int i=0;i<minans.size();i++) { int u,v,d; u = minans[i].u; v = minans[i].v; d = minans[i].d; if(ff[u]==v) { x +=(LL)sum[u]*(LL)((LL)n-sum[u])*d; } else if(ff[v]==u) { x +=(LL)sum[v]*(LL)((LL)n-sum[v])*d; } } LL mm = (LL)n*(LL)(n-1)/2; printf("%I64d %.2lf\n",ans,x*1.0/mm); } return 0; }