[HNOI2013]游走
[HNOI2013]游走
考虑每一条边的单独贡献,发现这个不是很好计算,而且边数其实很多。
我们考虑对于一条 $u \to v$ 的边,其贡献是 $\dfrac{f(u)}{deg(u)} + \dfrac{f(v)}{deg(v)}$。
其中 $f(i)$ 表示点 $i$ 期望被经过的次数,别忘了一开始点 $1$ 就被经过一次了。
考虑走到别的点之后再走回来更新这个点:
$$
f(u) = \sum_{v \in son(u)} \frac{f(v)}{deg(v)}
$$
如果 $u = 1$ 还要 $+ 1$。
发现数据范围很小,我们直接进行高斯消元即可。
之后对于边的期望经过次数进行贪心即可。
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 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
| #include <bits/stdc++.h> using namespace std;
#ifdef Fread char buf[1 << 21], *iS, *iT; #define gc() (iS == iT ? (iT = (iS = buf) + fread (buf, 1, 1 << 21, stdin), (iS == iT ? EOF : *iS ++)) : *iS ++) #define getchar gc #endif
template <typename T> void r1(T &x) { x = 0; char c(getchar()); int f(1); for(; c < '0' || c > '9'; c = getchar()) if(c == '-') f = -1; for(; '0' <= c && c <= '9';c = getchar()) x = (x * 10) + (c ^ 48); x *= f; }
template <typename T,typename... Args> inline void r1(T& t, Args&... args) { r1(t); r1(args...); }
const int maxn = 5e2 + 5; const int maxm = maxn << 1; const double eps = 1e-10;
int n, m; double a[maxn][maxn]; double deg[maxn]; vector<int> vc[maxn];
void add(int u,int v) { vc[u].push_back(v); }
double f[maxn];
void Guess() { for(int i = 1; i < n; ++ i) { int pos(i); for(int j = i + 1; j <= n; ++ j) if(fabs(a[j][i]) > fabs(a[pos][i])) pos = i; if(pos != i) for(int j = 1; j <= n + 1; ++ j) swap(a[pos][j], a[i][j]); for(int j = 1; j <= n; ++ j) if(fabs(a[j][i]) > eps && i != j) { double tmp = a[j][i] / a[i][i]; for(int k = 1; k <= n + 1; ++ k) a[j][k] -= tmp * a[i][k]; } } for(int i = 1; i < n; ++ i) f[i] = a[i][n + 1] / a[i][i]; f[n] = 0;
}
struct Edge { int u, v; double w; int operator < (const Edge &z) const { return w > z.w; } }E[maxn * maxn];
signed main() {
int i, j; r1(n, m); for(i = 1; i <= m; ++ i) {int u, v; r1(u, v), add(u, v), add(v, u); E[i].u = u, E[i].v = v;} for(i = 1; i <= n; ++ i) deg[i] = vc[i].size(); for(i = 1; i < n; ++ i) { for(int v : vc[i]) if(v != n) { a[i][v] = 1.0 / deg[v]; } a[i][i] = -1; } a[1][n + 1] = -1;
Guess();
for(i = 1; i <= m; ++ i) { E[i].w = (f[E[i].u] / deg[E[i].u] + f[E[i].v] / deg[E[i].v]); }
sort(E + 1, E + m + 1); double ans(0); for(i = 1; i <= m; ++ i) ans += i * E[i].w; printf("%.3lf\n", ans); return 0; }
|