[HNOI2013]游走

[HNOI2013]游走

考虑随机游走时一条边$(x,y)$被经过,只有两种情况,要么是我们走到了点$x$,然后随机钦定了$y$,要么就是反过来。我们假设一个点的度数为$deg[i]$,假设一个点期望会经过$t[u]$次,所以一个边所贡献的权值就是$w \times ( \frac{t[x]}{deg[x]} + \frac{t[y]}{deg[y]} )$。

所以现在我们的目标就是求$t$。发现$n \leq 500$我们可以考虑高消,具体而言,可以列出

特别的,对于第一个点必然会被经过一次,$t[1] = 1 + \sum \frac{t[v]}{deg[v]}$,而$t[n] = 0$,因为到达了$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
#include "iostream"
#include "algorithm"
#include "cstring"
#include "cstdio"
#include "cmath"
using namespace std;
#define MAXN 506
int n , m;
#define eps 1e-6
int deg[MAXN];
double A[MAXN][MAXN];
int gauss( ) {
for( int i = 1 ; i <= n ; ++ i ) { // cur : 第 i 行
int mxpos = i;
for( int j = i ; j <= n ; ++ j ) if( fabs( A[j][i] ) - fabs( A[mxpos][i] ) > eps )
mxpos = j;
for( int j = 1 ; j <= n + 1 ; ++ j )
swap( A[i][j] , A[mxpos][j] );
double c = A[i][i];
if( c == 0 ) { return 0; }
A[i][i] = 1;
for( int j = i + 1 ; j <= n + 1 ; ++ j )
A[i][j] /= c;
for( int j = 1 ; j <= n ; ++ j ) if( j != i ) { // cur : 第 j 行
double cc = A[j][i]; A[j][i] = 0;
for( int k = i + 1 ; k <= n + 1 ; ++ k ) // cur : 第 k 列
A[j][k] -= cc * A[i][k];
}
}
return 1;
}
pair<int,int> E[MAXN * MAXN];
double w[MAXN * MAXN];
int G[MAXN][MAXN];
int main() {
cin >> n >> m;
for( int i = 1 , u , v ; i <= m ; ++ i ) {
scanf("%d%d",&u,&v);
++ deg[u] , ++ deg[v]; G[u][v] = G[v][u] = 1;
E[i] = make_pair( u , v );
}
A[1][n + 1] = -1;
for( int i = 1 ; i < n ; ++ i )
for( int j = 1 ; j < n ; ++ j )
if( G[i][j] )
A[i][j] = 1.0 / deg[j];
else if( i == j ) A[i][j] = -1.0;
A[n][n] = 1;
// for( int i = 1 ; i <= n ; ++ i ) {
// for (int j = 1; j <= n + 1; ++j) printf("%.3f ", A[i][j]); puts("");
// }
gauss( );
// for( int i = 1 ; i <= n ; ++ i ) cout << A[i][n + 1] << endl;
for( int i = 1 ; i <= m ; ++ i ) {
int u = E[i].first , v = E[i].second;
w[i] = A[u][n + 1] / deg[u] + A[v][n + 1] / deg[v];
}
sort( w + 1 , w + 1 + m );
double res = 0;
for( int i = 1 ; i <= m ; ++ i ) res += ( m - i + 1 ) * w[i];
printf("%.3f",res);
}
文章作者: yijan
文章链接: https://yijan.co/old3/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Yijan's Blog