hdu 5723 Abandoned country 最小生成树+DFS
题意:给定N个顶点M条边的无向图,每条边包含一个权值,权值都
各不相同,求最小生成树并求最小生成树上的任意两点之间距离的最小期望。
分析:因为边权值各不相同,那么最小生成树是唯一的。那么只需要求最小生成树上的任意两点之间的距离之和除以N*(N-1)/2即可。对于求树上的任意两点之间的距离之和,我们可以从根节点DFS出发遍历求出每个结点的子树下的节点数之和+该节点本身的数目,记为sum[root]。然后考虑每个结点和它父亲节点的边,因为这条边的一端有sum[root]个节点,另外一端有N-sum[root]的节点,该边对于整个距离和的贡献就是(N-sum[root]) * 这条边的权值。那么时间复杂度就是O(Elog(E)+N)。思路同:
hdu 2376 Average distance
#include <cmath>
#include <queue>
#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <algorithm>
using namespace std;
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#define FIN freopen("input.txt","r",stdin)
#define FOUT freopen("output.txt","w",stdout)
#define fst first
#define snd second
typedef __int64 LL;
//typedef long long LL;
typedef unsigned int uint;
typedef pair<int, int> PII;
const int INF = 0x3f3f3f3f;
const double eps = 1e-6;
const int MAXN = 100000 + 5;
const int MAXM = 1000000 + 5;
struct Edge {
int u, v, w;
bool operator < (const Edge& e) const {
return w < e.w;
}
} edges[MAXM];
int T, N, M;
int par[MAXN], _rank[MAXN];
struct TNode {
int v, w;
TNode() {}
TNode(int v, int w) : v(v), w(w) {}
};
vector<TNode> G[MAXN];
LL sum[MAXN];
LL ans;
void init() {
memset(par, -1, sizeof(par));
memset(_rank, 0, sizeof(_rank));
// memset(vis, false, sizeof(vis));
memset(sum, 0, sizeof(sum));
for (int i = 1; i <= N; i++) G[i].clear();
}
int Find(int x) {
return -1 == par[x] ? x : (par[x] = Find(par[x]));
}
LL Kruskal() {
LL cost = 0;
int ecnt = 0;
init();
sort(edges, edges + M);
for (int i = 0; i < M && ecnt < N - 1; i++) {
Edge& e = edges[i];
int pu = Find(e.u);
int pv = Find(e.v);
if (pu == pv) continue;
if (_rank[pu] == _rank[pv]) {
par[pv] = pu;
_rank[pu] ++;
} else if (_rank[pu] > _rank[pv]) {
par[pv] = pu;
} else {
par[pu] = pv;
}
cost += e.w;
Find(e.u);
Find(e.v);
ecnt ++;
G[e.u].push_back(TNode(e.v, e.w));
G[e.v].push_back(TNode(e.u, e.w));
}
return cost;
}
void dfs(int root, int father) {
sum[root] = 1;
for (int i = 0; i < G[root].size(); i++) {
TNode& e = G[root][i];
int son = e.v;
if (son == father) continue;
dfs(son, root);
sum[root] += sum[son];
ans += (sum[son] * (N - sum[son])) * e.w;
}
}
int main() {
#ifndef ONLINE_JUDGE
FIN;
#endif // ONLINE_JUDGE
scanf("%d", &T);
while (T --) {
scanf("%d %d", &N, &M);
int u, v, w;
for (int i = 0; i < M; i++) {
scanf("%d %d %d", &u, &v, &w);
edges[i].u = u;
edges[i].v = v;
edges[i].w = w;
}
LL mincost = Kruskal();
ans = 0;
dfs(1, -1);
LL s = (LL)N * (N - 1) / 2;
printf("%lld %.2lf\n", mincost, (double) ans / s);
}
return 0;
}