题目链接:hdu 5723 Abandoned country
题目大意:N个点,M条边;先构成一棵最小生成树,然后这个最小生成树上求任意两点之间的路径长度和,并求期望
/**************************************************************
Problem:hdu 5723
User: youmi
Language: C++
Result: Accepted
Time:2932MS
Memory:22396K
solution:首先注意到任意两条边的边权是不一样的,由此得知最小生成树是唯一的,最小生成树既然是唯一的,
那么期望其实也就是唯一的,不存在什么最小期望。求完最小生成树之后,接下来的问题就可以转换成
在最小生成树上求任意两点之间距离的平均值,对于每条边,统计所 有的路径用到此边的次数,也就
是边的两端的点数之积。那么这条边的总贡献就是次数*边 权。最后得到所有边的贡献之和再除以总路
径数n*(n-1)/2n∗(n−1)/2就是答案。可以OnOn求出。任取一点为根dfs,对每个点ii记录其子树包
含的点数(包括其自身),设点数为sum[i]sum[i],则ii的父亲一侧的点数即为n-sum[i]n−sum[i]。
一边遍历一边统计就行。
****************************************************************/
//#pragma comment(linker, "/STACK:1024000000,1024000000")
//#include<bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <cmath>
#include <queue>
#include <deque>
#include <string>
#include <vector>
#define zeros(a) memset(a,0,sizeof(a))
#define ones(a) memset(a,-1,sizeof(a))
#define sc(a) scanf("%d",&a)
#define sc2(a,b) scanf("%d%d",&a,&b)
#define sc3(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define scs(a) scanf("%s",a)
#define sclld(a) scanf("%I64d",&a)
#define pt(a) printf("%d\n",a)
#define ptlld(a) printf("%I64d\n",a)
#define rep(i,from,to) for(int i=from;i<=to;i++)
#define irep(i,to,from) for(int i=to;i>=from;i--)
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
#define lson (step<<1)
#define rson (lson+1)
#define eps 1e-6
#define oo 0x3fffffff
#define TEST cout<<"*************************"<<endl
const double pi=*atan(1.0); using namespace std;
typedef long long ll;
template <class T> inline void read(T &n)
{
char c; int flag = ;
for (c = getchar(); !(c >= '' && c <= '' || c == '-'); c = getchar()); if (c == '-') flag = -, n = ; else n = c - '';
for (c = getchar(); c >= '' && c <= ''; c = getchar()) n = n * + c - ''; n *= flag;
}
int Pow(int base, ll n, int mo)
{
if (n == ) return ;
if (n == ) return base % mo;
int tmp = Pow(base, n >> , mo);
tmp = (ll)tmp * tmp % mo;
if (n & ) tmp = (ll)tmp * base % mo;
return tmp;
}
//*************************** int n,m;
const int maxn=+;
int T,head[maxn],fa[maxn],vis[maxn];
struct Edge
{
int u,v;
ll w;
void init(int _u,int _v,ll _w)
{
u=_u,v=_v,w=_w;
}
}edge[maxn*];
int get_f(int u)
{
return u==fa[u]?u:fa[u]=get_f(fa[u]);
}
bool cmp(Edge a,Edge b)
{
return a.w<b.w;
}
struct side
{
int v,next;
ll w;
}e[maxn*];
void init()
{
T=;
ones(head);
zeros(vis);
}
void build(int u,int v,ll w)
{
e[T].v=v;
e[T].w=w;
e[T].next=head[u];
head[u]=T++;
}
void kruskal()
{
sort(edge+,edge++m,cmp);
rep(i,,n)
fa[i]=i;
ll sum=;
rep(i,,m)
{
int f1=get_f(edge[i].u);
int f2=get_f(edge[i].v);
if(f1!=f2)
{
fa[f2]=f1;
build(edge[i].u,edge[i].v,edge[i].w);
build(edge[i].v,edge[i].u,edge[i].w);
sum+=edge[i].w;
//j++;
}
}
printf("%I64d ",sum);
}
double tt;
ll dfs(int u)
{
ll num=,temp=;
vis[u]=;
for(int i=head[u];~i;i=e[i].next)
{
int v=e[i].v;
ll w=e[i].w;
if(!vis[v])
{
temp=dfs(v);
tt+=1.0*w*(1.0*(n-temp)*temp);
num+=temp;
}
}
return num;
} void sovle()
{
tt=;
dfs();
tt=tt*2.0/(1.0*n*(n-));
printf("%.2lf\n",tt);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
int T_T;
scanf("%d",&T_T);
for(int kase=;kase<=T_T;kase++)
{
sc(n);
sc(m);
init();
int u,v;
ll w;
rep(i,,m)
{
sc2(u,v);sclld(w);
edge[i].init(u,v,w);
}
kruskal();
sovle();
}
}