【BZOJ】【3143】【HNOI2013】游走

数学期望/高斯消元/贪心

  啊……用贪心的思路明显是要把经过次数期望越大的边的权值定的越小,那么接下来的任务就是求每条边的期望经过次数。

  拆边为点?nonono,连接x,y两点的边的期望经过次数明显是 times[x]/du[x]+times[y]/du[y] 所以只要求出每个点的期望经过次数即可

  像「随机程序」那道题一样,(马尔可夫过程?)高斯消元求解即可

特别的,第1个点是起点,方程组的常数项为1,而     「第N个点是终点,期望经过次数为0,不参与消元」   (因为走到N就停下了,不会“经过”)(这个地方WA了……sigh)

 1 /**************************************************************
 2     Problem: 3143
 3     User: Tunix
 4     Language: C++
 5     Result: Accepted
 6     Time:3716 ms
 7     Memory:8284 kb
 8 ****************************************************************/
 9
10 //BZOJ 3143
11 #include<cmath>
12 #include<vector>
13 #include<cstdio>
14 #include<cstring>
15 #include<cstdlib>
16 #include<iostream>
17 #include<algorithm>
18 #define rep(i,n) for(int i=0;i<n;++i)
19 #define F(i,j,n) for(int i=j;i<=n;++i)
20 #define D(i,j,n) for(int i=j;i>=n;--i)
21 #define pb push_back
22 using namespace std;
23 int getint(){
24     int v=0,sign=1; char ch=getchar();
25     while(ch<‘0‘||ch>‘9‘){ if (ch==‘-‘) sign=-1; ch=getchar();}
26     while(ch>=‘0‘&&ch<=‘9‘){ v=v*10+ch-‘0‘; ch=getchar();}
27     return v*=sign;
28 }
29 const int N=510,M=250010;
30 const double eps=1e-8;
31 typedef double Matrix[N][N];
32 /******************tamplate*********************/
33 void gauss_jordan(Matrix A,int n){
34     int r;
35     rep(i,n){
36         r=i;
37         for(int j=i+1;j<n;j++)
38             if (fabs(A[j][i]) > fabs(A[r][i])) r=j;
39         if (fabs(A[r][i]) < eps) continue;
40         if (r!=i) F(j,0,n) swap(A[r][j],A[i][j]);
41         rep(k,n) if (k!=i)
42             D(j,n,i) A[k][j]-=A[k][i]/A[i][i]*A[i][j];
43     }
44 }
45
46 Matrix A;
47 int n,m,d[N],u[M],v[M];
48 double w[M],x[N];
49 vector<int>G[N];
50
51 int main(){
52 #ifndef ONLINE_JUDGE
53     freopen("3143.in","r",stdin);
54     freopen("3143.out","w",stdout);
55 #endif
56     n=getint(); m=getint();
57     F(i,1,m){
58         u[i]=getint()-1; v[i]=getint()-1;
59         G[u[i]].pb(v[i]); G[v[i]].pb(u[i]);
60     }
61     rep(i,n) d[i]=G[i].size();
62     memset(A,0,sizeof (A));
63     rep(i,n-1){
64         A[i][i]=1;
65         rep(j,G[i].size())
66             A[i][G[i][j]]=-1.0/d[G[i][j]];
67         if (i==0) A[i][n]=1.0;
68     }
69
70     gauss_jordan(A,n);
71     rep(i,n) x[i]=A[i][n]/A[i][i];
72     x[n-1]=0;
73     F(i,1,m) w[i]=x[u[i]]/d[u[i]]+x[v[i]]/d[v[i]];
74     sort(w+1,w+m+1);
75     double ans=0.0;
76     F(i,1,m) ans+=w[m-i+1]*i;
77     printf("%.3lf\n",ans);
78     return 0;
79 }

时间: 2024-10-14 06:19:55

【BZOJ】【3143】【HNOI2013】游走的相关文章

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 游走 高斯消元 期望

这道题是我第一次使用高斯消元解决期望类的问题,首发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]游走(数学期望)

题目: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

bzoj 3143 随机游走

题意: 给一个简单无向图,一个人从1号节点开始随机游走(即以相同概率走向与它相邻的点),走到n便停止,问每条边期望走的步数. 首先求出每个点期望走到的次数,每条边自然是从它的两个端点走来. 1 /************************************************************** 2 Problem: 3143 3 User: idy002 4 Language: C++ 5 Result: Accepted 6 Time:736 ms 7 Memory:

【BZOJ】3143: [Hnoi2013]游走 期望+高斯消元

[题意]给定n个点m条边的无向连通图,每条路径的代价是其编号大小,每个点等概率往周围走,要求给所有边编号,使得从1到n的期望总分最小(求该总分).n<=500. [算法]期望+高斯消元 [题解]显然,应使经过次数越多的边编号越小,问题转化为求每条边的期望经过次数. 边数太多,容易知道f(u,v)=f(u)/out(u)+f(v)/out(v),所以转化为求每个点的期望经过次数,这就是驱逐猪猡了. 设f[x]表示点x的期望经过次数,根据全期望公式(讨论"经过"的问题不能依赖于下一步