bzoj 3143 随机游走
题意:
给一个简单无向图,一个人从1号节点开始随机游走(即以相同概率走向与它相邻的点),走到n便停止,问每条边期望走的步数.
首先求出每个点期望走到的次数,每条边自然是从它的两个端点走来.
1 /************************************************************** 2 Problem: 3143 3 User: idy002 4 Language: C++ 5 Result: Accepted 6 Time:736 ms 7 Memory:9956 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <cmath> 12 #include <algorithm> 13 #define N 510 14 #define M N*N 15 using namespace std; 16 17 int n, m; 18 int head[N], dest[M], next[M], etot; 19 int dgr[N], uu[M], vv[M], qu[M]; 20 double ww[M]; 21 double a[N][N]; 22 23 void adde( int u, int v ) { 24 etot++; 25 dest[etot] = v; 26 next[etot] = head[u]; 27 head[u] = etot; 28 } 29 void gauss() { 30 int i, j, k; 31 for( i=1; i<=n; i++ ) { 32 j=i; 33 for( k=i+1; k<=n; k++ ) 34 if( fabs(a[k][i])>fabs(a[j][i]) ) j=k; 35 for( k=i; k<=n+1; k++ ) 36 swap( a[j][k], a[i][k] ); 37 for( j=i+1; j<=n; j++ ) { 38 double r = a[j][i]/a[i][i]; 39 for( k=i; k<=n+1; k++ ) 40 a[j][k] -= a[i][k]*r; 41 } 42 } 43 for( int i=n; i>=1; i-- ) { 44 a[i][n+1] /= a[i][i]; 45 a[i][i] = 1.0; 46 for( int j=i-1; j>=1; j-- ) { 47 a[j][n+1] -= a[j][i]*a[i][n+1]; 48 a[j][i] = 0.0; 49 } 50 } 51 } 52 bool cmp( int a, int b ) { 53 return ww[a] > ww[b]; 54 } 55 int main() { 56 scanf( "%d%d", &n, &m ); 57 for( int i=1; i<=m; i++ ) { 58 scanf( "%d%d", uu+i, vv+i ); 59 adde( uu[i], vv[i] ); 60 adde( vv[i], uu[i] ); 61 dgr[uu[i]]++; 62 dgr[vv[i]]++; 63 } 64 for( int i=1; i<=n; i++ ) 65 a[i][i] = -1.0; 66 a[1][n+1] = -1; 67 for( int u=1; u<=n; u++ ) { 68 for( int t=head[u]; t; t=next[t] ) { 69 int v=dest[t]; 70 if( v==n ) continue; 71 a[u][v] += 1.0/dgr[v]; 72 } 73 } 74 gauss(); 75 for( int i=1; i<=m; i++ ) { 76 int u=uu[i], v=vv[i]; 77 if( u!=n ) ww[i]+=a[u][n+1]/dgr[u]; 78 if( v!=n ) ww[i]+=a[v][n+1]/dgr[v]; 79 } 80 for( int i=1; i<=m; i++ ) 81 qu[i] = i; 82 sort( qu+1, qu+1+m, cmp ); 83 double ans = 0.0; 84 for( int i=1; i<=m; i++ ) 85 ans += i * ww[qu[i]]; 86 printf( "%.3lf\n", ans ); 87 } 88