2016 多校第一场 hdu 5723(最小生成树+dfs)

来源:互联网 发布:webshell是什么 编辑:程序博客网 时间:2024/06/05 21:36

题解:跑一遍最小生成树,因为每条边长度不同所以跑不出来的答案就只有一种,对于求解任意两点的期望,只要把任意两点的距离累加和再除以总数即可,对于计算累加和,我借鉴了别人的方法,对于每条边,算出它左边有n个点,右边有m个点,那么这条边就会被用到n*m次 ,对所有的边都这么算一遍,答案累加就可以了


#include <iostream>#include <cstdio>#include <cstring>#include <queue>#include <algorithm>#include <string>#include <map>#include <math.h>#include <queue>#include <climits>#include <stack>using namespace std;struct node {    int op, ed;    int len;    bool operator<(const node &x)const{        return len < x.len;    }}edge[1000005];int father[100005], ret[1000005], dep[100005];int cnt;int n, m;vector<int> graph[100005];int find_(int x){    if(father[x] == x)        return x;    else        return father[x] = find_(father[x]);}int dfs(int now, int pre){    int ans = 1;    for(int i = 0; i < graph[now].size(); i++){        if(graph[now][i] != pre)            ans += dfs(graph[now][i], now);    }    dep[now] = ans;    return ans;    }void init(){    for(int i = 1; i <= n; i++)        father[i] = i;    memset(dep, 0, sizeof(dep));}long long kruskal(){    long long answer = 0;    sort(edge, edge + m);    for(int i = 0; i < m; i++){        int a = edge[i].op, b = edge[i].ed;        int x = find_(a), y = find_(b);        if(x == y) continue;        father[x] = y;        ret[cnt++] = i;        answer += edge[i].len;        graph[a].push_back(b);        graph[b].push_back(a);        if(cnt == n - 1) break;    }    return answer;}int main(){    int t;    scanf("%d", &t);    while(t--){        scanf("%d%d", &n, &m);        for(int i = 1; i <= n; i++)            graph[i].clear();        cnt = 0;        for(int i = 0; i < m; i++)            scanf("%d %d %d", &edge[i].op, &edge[i].ed, &edge[i].len);        init();        long long ans1 = kruskal();        double sum1 = 0;        dfs(1, -1);        for(int i = 0; i < cnt; i++){            int x = edge[ret[i]].op, y = edge[ret[i]].ed;            int tmp = min(dep[x], dep[y]);            int maxn = n - tmp;            sum1 += 1ll * tmp * maxn * edge[ret[i]].len;        }        printf("%lld %.2lf\n", ans1, sum1 / (1ll * n * (n - 1) / 2));    }    return 0;}


1 0
原创粉丝点击