题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5723
题目大意:找出最小生成树以及任意两点间距离的期望。
思路:根据图建立最小生成树,然后DFS求距离和然后求期望即可。
求出来最小生成树需要重新建图,建图需要 双向 边,然后DFS求出每条边贡献的次数,除以总共多少种情况就可以了,,。,,,,,,,
ps:比赛时代码写残疾了**
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <cmath>
#include <stack>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <stdlib.h>
#include <iomanip>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define maxn 100005
#define MOD 1000000007
#define mem(a , b) memset(a , b , sizeof(a))
#define LL long long
#define ULL unsigned long long
#define FOR(i , n) for(int i = 1 ; i<= n ; i ++)
typedef pair<int , int> pii;
vector<pii>v[maxn];
int per[maxn] , num[maxn];
bool vis[maxn];
int n , m;
LL ans1 ;
double ans2;
struct node
{
int u , v , w;
}e[maxn*10];
bool cmp(node n1 , node n2)
{
return n1.w < n2.w;
}
void add(int fr , int to , int w)
{
v[fr].push_back(make_pair(to , w));
v[to].push_back(make_pair(fr , w));
}
int findfa(int x)
{
if(per[x] == x) return per[x];
else return per[x] = findfa(per[x]);
}
void Kru()
{
for(int i = 0 ; i <= n ; i ++) per[i] = i , v[i].clear();
for(int i = 0 ; i < m ; i ++)
{
int a = findfa(e[i].u);
int b = findfa(e[i].v);
if(a != b)
{
per[b] = a;
ans1 += e[i].w;
add(min(e[i].u ,e[i].v) , max(e[i].u , e[i].v) , e[i].w);
}
}
}
int DFS(int pos , int w)
{
vis[pos] = 1;
int up = v[pos].size();
for(int i = 0 ; i < up ; i ++)
{
pii pi = v[pos][i];
if(!vis[pi.first]) num[pos] += DFS(pi.first , pi.second);
}
ans2 += 2.0 * w * (n - num[pos] - 1) * (num[pos] + 1) / n / (n-1);
if(up <= 0) return 1;
else return num[pos] + 1;
}
int main()
{
int t;
cin >> t;
while(t --)
{
scanf("%d %d" , &n , &m);
ans1 = ans2 = 0;
mem(num , 0);mem(vis , 0);
for(int i = 0 ; i < m ; i ++)
{
scanf("%d %d %d" , &e[i].u , &e[i].v , &e[i].w);
}
sort(e , e + m , cmp);
Kru();
DFS(1 , 0);
//cout << ans1 << endl;
printf("%lld %.2lf\n" , ans1 , ans2);
}
return 0;
}