[LibreOJ 2383][HNOI2013]游走
转载请注明出处:http://danihao123.is-programmer.com/
本野蛮人竟然没做过高消期望DP,,,泪,流了下来,,,
根据期望线性性,答案就是所有边的期望被走的次数乘上边的编号的和。一条边期望经过的次数可以根据他两个端点期望经过的次数来算(但是\(n\)要特判一下),要求所有点期望走过的次数当然就可以列\(n\)个方程然后高消力。然后期望走的次数多的边编号应该小,反之亦然,所以求完每条边走的次数的期望之后就贪心一下就好力。
代码:
#include <cstdio> #include <cstring> #include <cstdlib> #include <cassert> #include <algorithm> #include <utility> #include <cmath> const int maxn = 505; const int maxm = maxn * maxn; using R = double; const R eps = 1e-9; int sign(R x) { if(fabs(x) < eps) { return 0; } else { return ((x < 0.00) ? -1 : 1); } } R D[maxn][maxn]; int n; void gauss() { #ifdef LOCAL for(int i = 1; i <= n; i ++) { for(int j = 1; j <= n + 1; j ++) { printf("%.3lf ", D[i][j]); } puts(""); } #endif for(int i = 1; i <= n; i ++) { int r = i; for(int j = i + 1; j <= n; j ++) { if(fabs(D[j][i]) > fabs(D[r][i])) { r = j; } } assert(sign(D[r][i]) != 0); if(r != i) { for(int j = 1; j <= n + 1; j ++) { std::swap(D[i][j], D[r][j]); } } for(int k = i + 1; k <= n; k ++) { R rate = D[k][i] / D[i][i]; for(int j = i; j <= n + 1; j ++) { D[k][j] -= D[i][j] * rate; } } } for(int i = n; i >= 1; i --) { for(int j = i + 1; j <= n; j ++) { D[i][n + 1] -= D[j][n + 1] * D[i][j]; D[i][j] = 0; } D[i][n + 1] /= D[i][i]; D[i][i] = 1; #ifdef LOCAL printf("E[%d] : %.3lf\n", i, D[i][n + 1]); #endif } } int E[maxm][2], deg[maxn]; R tms[maxm]; void add_edge(int u, int v) { if(u != n) D[v][u] += 1.00 / (R(deg[u])); } int main() { int m; scanf("%d%d", &n, &m); for(int i = 1; i <= n; i ++) { D[i][i] = -1; } D[1][n + 1] = -1; for(int i = 1; i <= m; i ++) { scanf("%d%d", &E[i][0], &E[i][1]); deg[E[i][0]] ++; deg[E[i][1]] ++; } for(int i = 1; i <= m; i ++) { int u = E[i][0], v = E[i][1]; add_edge(u, v); add_edge(v, u); } gauss(); for(int i = 1; i <= m; i ++) { tms[i] = 0; int u = E[i][0], v = E[i][1]; if(u != n) tms[i] += D[u][n + 1] / (R(deg[u])); if(v != n) tms[i] += D[v][n + 1] / (R(deg[v])); } std::sort(tms + 1, tms + 1 + m, [&](const R &i, const R &j) { return i > j; }); R ans = 0; for(int i = 1; i <= m; i ++) { ans += tms[i] * (R(i)); } printf("%.3lf\n", ans); return 0; }