P3232 [HNOI2013]游走
考虑求出每个边期望下经过的次数,边很多,考虑求经过每个点的个数,从而算出经过边的次数,这样排序后期望次数小的边赋值大。考虑在点上做高斯消元。因为在 $n$ 点直接停止了,所以 $n$ 不会给边带来任何贡献,所以可以不考虑 $n$ 点,以免算重。
查看代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
| #include <cstdio> #include <cmath> #include <vector> #include <algorithm> using namespace std; template <class Type> void read(Type &x) { char c; bool flag = false; while ((c = getchar()) < '0' || c > '9') c == '-' && (flag = true); x = c - '0'; while ((c = getchar()) >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0'; flag && (x = ~x + 1); } template <class Type> void write(Type x) { x < 0 && (putchar('-'), x = ~x + 1); x > 9 && (write(x / 10), 0); putchar(x % 10 + '0'); } const int N = 510, M = 125e3 + 10; int n, m, d[N]; double A[N][N], f[N]; struct Node { int u, v; } e[M]; vector <int> g[N]; void Gauss () { for (int k = 1; k < n; k++) { int t = k; for (int i = k + 1; i < n; i++) fabs(A[i][k]) > fabs(A[t][k]) && (t = i); swap(A[k], A[t]); for (int i = 1; i < n; i++) { if (i == k) continue; double t = A[i][k] / A[k][k]; for (int j = k + 1; j <= n; j++) A[i][j] -= A[k][j] * t; } } for (int i = 1; i < n; i++) A[i][n] /= A[i][i]; } int main () { read(n), read(m); for (int i = 1; i <= m; i++) { read(e[i].u), read(e[i].v); g[e[i].u].push_back(e[i].v); g[e[i].v].push_back(e[i].u); d[e[i].u]++, d[e[i].v]++; } for (int i = 1; i < n; i++) { A[i][i] = 1; for (int j : g[i]) j ^ n && (A[j][i] = -1.0 / d[i]); } A[1][n] = 1; Gauss(); for (int i = 1; i <= m; i++) f[i] = A[e[i].u][n] / d[e[i].u] + A[e[i].v][n] / d[e[i].v]; sort(f + 1, f + m + 1); double res = 0; for (int i = 1; i <= m; i++) res += (m - i + 1) * f[i]; printf("%.3lf", res); return 0; }
|