[HDOJ5723]Abandoned country(最小生成树,期望)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5723

题意:求最小生成树,并且求这棵最小生成树上所有边走过次数的期望。

走过次数的期望=Σ边被走过次数*边权/(n*(n-1)/2)

求边被走过的次数,相当于关心这个边的两侧分别有多少点,走的次数就是两边的点数的乘积这个很好理解。可以从边的一侧开始dfs,找到这个边的一侧点数x,由于最小生成树是联通的,那么边的另一侧点数一定是n-x。所以这条边的贡献是(n-x)*x*w。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 typedef long long LL;
 5 typedef struct Edge {
 6   int v, next;
 7   LL w;
 8 }Edge;
 9 
10 typedef struct E {
11   int u, v;
12   LL w;
13 }E;
14 const int maxn = 200100;
15 const int maxm = 1000100;
16 int n, m;
17 E e[maxm<<1];
18 Edge edge[maxm<<1];
19 int head[maxn], ecnt;
20 int pre[maxn];
21 LL ret1, ret2;
22 
23 int find(int x) {
24   return x == pre[x] ? x : pre[x] = find(pre[x]);
25 }
26 
27 bool unite(int x, int y) {
28   x = find(x); y = find(y);
29   if(x != y) {
30     pre[x] = y;
31     return 1;
32   }
33   return 0;
34 }
35 
36 void init() {
37   memset(head, -1, sizeof(head));
38   ecnt = 0; ret1 = 0; ret2 = 0;
39   for(int i = 1; i <= n; i++) pre[i] = i;
40 }
41 
42 void adde(int u, int v, LL w) {
43   edge[ecnt].v = v; edge[ecnt].w = w; edge[ecnt].next = head[u]; head[u] = ecnt++;
44   edge[ecnt].v = u; edge[ecnt].w = w; edge[ecnt].next = head[v]; head[v] = ecnt++;
45 }
46 
47 bool cmp(E a, E b) {
48   return a.w < b.w;
49 }
50 
51 int dfs(int u, int p) {
52   int siz = 1;
53   for(int i = head[u]; ~i; i=edge[i].next) {
54     int v = edge[i].v; LL w = edge[i].w;
55     if(p == v) continue;
56     int pre = dfs(v, u);
57     siz += pre;
58     ret2 += (LL)pre * (LL)(n - pre) * w;
59   }
60   return siz;
61 }
62 
63 int main() {
64   //freopen("in", "r", stdin);
65   int T, u, v;
66   LL w;
67   scanf("%d", &T);
68   while(T--) {
69     scanf("%d%d",&n,&m);
70     init();
71     for(int i = 0; i < m; i++) {
72       scanf("%d%d%lld",&u,&v,&w);
73       e[i].u = u; e[i].v = v; e[i].w = w;
74     }
75     sort(e, e+m, cmp);
76     for(int i = 0; i < m; i++) {
77       u = e[i].u; v = e[i].v; w = e[i].w;
78       if(unite(u, v)) {
79         ret1 += w;
80         adde(u, v, w);
81       }
82     }
83     dfs(1, -1);
84     LL k = n * (n - 1);
85     printf("%lld %.2lf\n", ret1, 2.0*ret2/(double)k);
86   }
87   return 0;
88 }

 

posted @ 2016-10-19 20:46  Kirai  阅读(218)  评论(0编辑  收藏  举报