HDU 5723 (最小生成树 树DP)

来源:互联网 发布:aspx网站源码修改教程 编辑:程序博客网 时间:2024/05/19 06:48

题目链接:点击这里

题意:求一个图的最小生成树, 并且在这个最小生成树的基础上, 求随机取两个点不同的点的路径长度的期望。

最小生成树直接可以求出来,然后枚举每一条边对期望的贡献即可。

#include <cstdio>#include <cstring>#include <algorithm>#include <iostream>#include <cmath>using namespace std;#define maxn 100005#define maxm 1000005int n, m;struct node {    int v, next, w;}edge[maxn*2];int head[maxn], cnt;struct E {    int u, v, w;    bool operator < (const E &a) const {        return w < a.w;    }}e[maxm];int fa[maxn];#define find Findint find (int x) {    return fa[x] == x ? fa[x] : fa[x] = find (fa[x]);}void add_edge (int u, int v, int w) {    edge[cnt].v = v, edge[cnt].next = head[u], edge[cnt].w = w, head[u] = cnt++;}int sz[maxn];void dfs (int u, int fa) {    sz[u] = 1;    for (int i = head[u]; i != -1; i = edge[i].next) {        int v = edge[i].v;        if (v == fa)            continue;        dfs (v, u);        sz[u] += sz[v];    }}double res;void dfs1 (int u, int fa) {    for (int i = head[u]; i != -1; i = edge[i].next) {        int v = edge[i].v;        if (v == fa)            continue;        int s2 = sz[v], s1 = sz[1]-sz[v];        res += 1.0*edge[i].w*s1*s2*2/(1.0*n*(n-1));        dfs1 (v, u);    }}int main () {    int t;    scanf ("%d", &t);    while (t--) {        scanf ("%d%d", &n, &m);        for (int i = 0; i < m; i++) {            scanf ("%d%d%d", &e[i].u, &e[i].v, &e[i].w);        }        sort (e, e+m);        for (int i = 1; i <= n; i++) fa[i] = i;        memset (head, -1, sizeof head);        cnt = 0;        long long ans = 0;        for (int i = 0; i < m; i++) {            int p1 = find (e[i].u), p2 = find (e[i].v);            if (p1 != p2) {                add_edge (e[i].u, e[i].v, e[i].w);                add_edge (e[i].v, e[i].u, e[i].w);                fa[p1] = p2;                ans += e[i].w;            }        }        memset (sz, 0, sizeof sz);        dfs (1, 0);        res = 0;        dfs1 (1, 0);        printf ("%lld %.2f\n", ans, res);    }    return 0;}
0 0
原创粉丝点击