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 

时间: 2024-10-09 18:55:10

bzoj 3143 随机游走的相关文章

BZOJ 3143 HNOI2013 游走 高斯消元 期望

这道题是我第一次使用高斯消元解决期望类的问题,首发A了,感觉爽爽的.... 中文题目,就不翻大意了,直接给原题: 一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点的某条边,沿着这条边走到下一个顶点,获得等于这条边的编号的分数.当小Z 到达N号顶点时游走结束,总分为所有获得的分数之和. 现在,请你对这M条边进行编号,使得小Z获得的总分的期望值最小. 输出最小的总分期望值. Solution: 这题贪心很明显

[BZOJ 3143][Hnoi2013]游走(高斯消元+期望)

Description 一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点的某条边,沿着这条边走到下一个顶点,获得等于这条边的编号的分数.当小Z 到达N号顶点时游走结束,总分为所有获得的分数之和. 现在,请你对这M条边进行编号,使得小Z获得的总分的期望值最小. Solution 对于点u(u≠1):到达u的概率 f[u]=∑f[v]/d[v] (Edges(u,v)) 而f[1]=∑f[v]/d[v]+1

BZOJ 3143: [Hnoi2013]游走( 高斯消元 )

我一开始的想法是设f(x)表示点x到N路径的期望长度, 那么f(u) = (∑f(v)+w(u,v)) / degreeu, f(N)=0, 我们代入入消元应该可以得到f(1)关于各条边长的关系式f(1)=∑we..然后贪心, 按照他们的系数来给边权...但是不会实现..但是我感觉是可行的..PoPoQQQ题解:http://blog.csdn.net/PoPoQQQ/article/details/42234607 ---------------------------------------

[BZOJ 3143][HNOI2013]游走(数学期望)

题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3143 分析: 易得如果知道了每条边经过的数学期望,那就可以贪心着按每条边的期望的大小赋值,所以问题就是如何求每条边的期望. 直接求没办法求的,可以先求出每个点经过的期望. 易得f[i]=∑f[j]/d[j] j->i有边 特殊的,对于起点,因为刚开始就在,所以应该是f[1]=1+∑f[j]/d[j]:对于终点,到了终点后不能再到其他节点,所以对其他边并没有贡献,所以f[n]=0 然后

●BZOJ 3143 [Hnoi2013]游走

题链: http://www.lydsy.com/JudgeOnline/problem.php?id=3143题解: 期望dp,高斯消元 首先有这样一种贪心分配边的编号的方案:(然后我没想到,233) 我们按每一条边的期望经过次数去分配编号, 具体来说,就是期望经过次数越多的边,分配的编号越小,反之则编号越大. 然后问题转化为如何求一条边的期望经过次数.(把求边的期望转化为求点的期望) 我们定义cnt[i]表示i点的出度,dp[i]表示期望经过i点的次数. 然后对于一个边(u,v),期望经过该

bzoj 3143: [Hnoi2013]游走

高斯消元 对于边可能很多,那我们计录点的期望次数就行了. 1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<queue> 7 #include<algorithm> 8 #include<vector> 9 #define M 1009 10 #

BZOJ 3143 HNOI2013 游走 期望DP+高斯消元

题目大意:给定一个无向连通图,我们需要给每条边附一个1~m的不重复的权值,使1到n的期望权值和最小 首先贪心思想是求出每条边的期望经过次数 然后对期望值最小的边附加m的权值,第二小的边附加m-1的权值,以此类推. 令f[i]为第i个点的期望经过次数 那么每条边的期望经过次数就是f[x]/d[x]+f[y]/d[y] 其中d[x]表示x的度数 那么显然有: f[1]=1+Σ[1->j]f[j]/d[j] f[i]=Σ[i->j]f[j]/d[j] (2<=i<=n-1) 其中f[n]

bzoj 3143 [Hnoi2013]游走【高斯消元+dp】

参考:http://blog.csdn.net/vmurder/article/details/44542575 和2337有点像 设点u的经过期望(还是概率啊我也分不清,以下都分不清)为\( x[u] \) ,度为 \( in[u] \),边\( (u,v) \) 的经过期望为 \( \frac{x[u]}{in[u]}+\frac{x[v]}{in[v]} \) 那么转换为求每个点的经过期望,\( x[u]=\sum_{v}^{v\subset son(u)}\frac{x[v]}{in[v

随机游走

在python中,可以利用数组操作来模拟随机游走. 下面是一个单一的200步随机游走的例子,从0开始,步长为1和-1,且以相等的概率出现.纯Python方式实现,使用了内建的 random 模块: # 随机游走 import matplotlib.pyplot as plt import random position = 0 walk = [position] steps = 200 for i in range(steps): step = 1 if random.randint(0, 1)