标签:
题目说每条边权值都不一样,说明最小生成树是唯一的,不存在最小期望这一说。
然后就是先求出最小生成树,随便确定一个根节点,计算出每个点的子树有多少节点,记为c[x]。
指向x的这条边被统计的次数为c[x]*(n-c[x])。然后基本就可以算出答案了。
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<map> #include<set> #include<queue> #include<stack> #include<iostream> using namespace std; typedef long long LL; const int maxn = 100000 + 10; int T, n, m, f[maxn], c[maxn]; bool flag[maxn]; struct Edge { int u, v; LL cost; }e[10 * maxn], ee[maxn]; vector<int>g[maxn]; double fz, fm; int Find(int x) { if (x != f[x]) f[x] = Find(f[x]); return f[x]; } bool cmp(const Edge&a, const Edge&b) { return a.cost < b.cost; } void dfs(int x,int f) { flag[x] = 1; c[x] = 1; for (int i = 0; i < g[x].size(); i++) { int id = g[x][i]; if (flag[ee[id].v]) continue; dfs(ee[id].v,id); c[x] = c[x] + c[ee[id].v]; } if (f != -1) fz = fz + 1.0*ee[f].cost*1.0*c[x] * 1.0* (n - c[x]); } int main() { scanf("%d", &T); while (T--) { scanf("%d%d", &n, &m); for (int i = 1; i <= m; i++) scanf("%d%d%lld", &e[i].u, &e[i].v, &e[i].cost); sort(e + 1, e + 1 + m, cmp); LL ans = 0; for (int i = 1; i <= n; i++) f[i] = i, g[i].clear(); int sz = 0; for (int i = 1; i <= m; i++) { int fx = Find(e[i].u), fy = Find(e[i].v); if (fx != fy) { f[fx] = fy, ans = ans + e[i].cost; ee[sz].u = e[i].u, ee[sz].v = e[i].v, ee[sz].cost = e[i].cost; g[e[i].u].push_back(sz++); ee[sz].u = e[i].v, ee[sz].v = e[i].u, ee[sz].cost = e[i].cost; g[e[i].v].push_back(sz++); } } memset(c, fz=0, sizeof c); memset(flag, fm=0, sizeof flag); dfs(1, -1); fm = 1.0*n*1.0*(n - 1) / 2.0; printf("%lld %.2lf\n", ans, fz / fm); } return 0; }
标签:
原文地址:http://www.cnblogs.com/zufezzt/p/5693350.html