D. The Child and Zoo

 

http://codeforces.com/contest/437/problem/D

 

排序+并查集

 

为了理解原理,让我们先画一个圈:

 


其中红边无限大,黑边值为0

 

我们可以发现,红边的值:1、直接就是f(1,2),2、毫不影响剩下的f(1,3)、f(1,4)、f(2,3)、f(2,4)、f(3,4)的值

所以对应的,我们可以得出:1、当它是图里最大的边时,它的贡献可求,2、球完之后,它唯一的作用就是确保连通性,除此之外就是个摆设

 

而题目里求所有点对的f()值等价于求所有边对所有点对的贡献

解决1用排序,解决2用并查集

 

 

 1 import java.util.Arrays;
 2 import java.util.Scanner;
 3 
 4 import static java.lang.Math.min;
 5 
 6 public class Main {
 7     static final int MAX = Integer.MAX_VALUE;
 8     static int[] f = new int[100000 + 50];
 9 
10     public static void main(String[] args) {
11         Scanner io = new Scanner(System.in);
12         int n = io.nextInt(), m = io.nextInt();
13 
14         int[] a = new int[n + 1], c = new int[n + 1];
15         for (int i = 1; i <= n; i++) {
16             a[i] = io.nextInt();
17             f[i] = i;
18             c[i] = 1;
19         }
20 
21         P[] ps = new P[m];
22         for (int i = 0, aa, bb; i < m; i++) {
23             aa = io.nextInt();
24             bb = io.nextInt();
25             ps[i] = new P(aa, bb, min(a[aa], a[bb]));
26         }
27 
28         Arrays.sort(ps);
29         double w = 0;
30         for (int i = 0, fx, fy, v; i < m; i++) {
31             P p = ps[i];
32             fx = find(p.x);
33             fy = find(p.y);
34             v = p.v;
35             if (fx == fy) continue;
36             //这道题这里和下面非常容易溢出,升double是必须的
37             // 并且1L和1.0【一定】要放在最前面,因为它是一边乘一边检测
38             // 什么时候碰到1.0就什么时候升double
39             w += 1L * v * c[fx] * c[fy];
40             f[fx] = fy;
41             c[fy] += c[fx];
42         }
43         //下面
44         System.out.println(w / (1.0 * n * (n - 1) / 2));
45     }
46 
47     static int find(int x) {
48         return f[x] == x ? x : (f[x] = find(f[x]));
49     }
50 
51     static class P implements Comparable<P> {
52         int x, y, v;
53 
54         public P(int x, int y, int v) {
55             this.x = x;
56             this.y = y;
57             this.v = v;
58         }
59 
60         @Override
61         public int compareTo(P o) {
62             return -v + o.v;
63         }
64     }
65 }

 

posted @ 2019-08-25 23:53  dodoBehind  阅读(188)  评论(0编辑  收藏  举报