bzoj3143 游走 [高斯消元+概率]
2017-03-12 09:45
162 查看
Description
一个无向连通图,顶点从1编号到N,边从1编号到M。 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选择当前顶点的某条边,沿着这条边走到下一个顶点,获得等于这条边的编号的分数。当小Z到达N号顶点时游走结束,总分为所有获得的分数之和。 现在,请你对这M条边进行编号,使得小Z获得的总分的期望值最小。Input
第一行是正整数N和M,分别表示该图的顶点数和边数,接下来M行每行是整数u,v(1≤u,v≤N),表示顶点u与顶点v之间存在一条边。 输入保证30%的数据满足N≤10,100%的数据满足2≤N≤500且是一个无向简单连通图。Output
仅包含一个实数,表示最小的期望值,保留3位小数。Sample Input
3 32 3
1 2
1 3
Sample Output
3.333HINT
边(1,2)编号为1,边(1,3)编号2,边(2,3)编号为3。Solution
这道题要求编号后期望的最小得分,为了使得分最小,那么就应该让出现期望大的边编号尽量小.这样我们就把问题转换成了求边的期望出现概率,然后贪心地编号即可.我们接着考虑,如何求边的期望出现概率呢?我们可以通过求出这两条边端点的出现概率除以各自度数然后加和,于是我们顺利把这道题转换成了求点出现概率的题目.对每个点列方程,高斯消元求解既可,需要特别注意的是起始点求概率时要+1,因为它是一定会出现的!Code
#include<bits/stdc++.h> #define maxn 3010 #define eps 1e-6 // #define COGS // #define DEBUG using namespace std; int n,m,num_edge=0; int edge[maxn][maxn]; double answer=0; double a[maxn][maxn],ans[maxn],deg[maxn]; inline int dcmp(double x) { if(abs(x)<=eps) return 0; else return x>0?1:-1; } inline int read() { char ch; int read=0,sign=1; do ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-'); if(ch=='-') sign=-1,ch=getchar(); while(ch>='0'&&ch<='9') { read=read*10+ch-'0'; ch=getchar(); } return sign*read; } void pre_work() { n=read(),m=read();n--; for(int i=1,u,v;i<=m;++i) u=read(),v=read(),edge[u][v]=edge[v][u]=1,deg[u]++,deg[v]++; for(int i=1;i<=n;++i) { a[i][i]=1,deg[i]=1.0/deg[i]; } for(int i=1;i<=n;++i) for(int j=1;j<=n+1;++j) if(edge[i][j]) a[j][i]-=deg[i]; a[1][n+1]=1; #ifdef DEBUG cerr<<"begin"<<endl; for(int i=1;i<=n;++i){ for(int j=1;j<=n+1;++j) cerr<<a[i][j]<<" "; cerr<<endl;} #endif } void print() { int cnt=0; for(int i=1;i<=n;++i) for(int j=1;j<=n+1;++j) if(edge[i][j]) { ans[++cnt]=a[i][n+1]*deg[i]; ans[cnt]+=a[j][n+1]*deg[j]; edge[j][i]=0; } sort(ans+1,ans+cnt+1); #ifdef DEBUG cerr<<"ans[]:"<<endl; for(int i=1;i<=cnt;++i) cerr<<ans[i]<<endl; #endif for(int i=1;i<=cnt;++i) answer+=ans[i]*(cnt-i+1); printf("%.3lf\n",answer); } void gauss() { for(int i=1;i<=n;++i) { if(!dcmp(a[i][i])) { int k=i; while(!dcmp(a[k][k])) k++; swap(a[k],a[i]); } for(int j=i+1;j<=n;++j) { for(int k=i+1;k<=n+1;++k) a[j][k]-=a[i][k]*(a[j][i]/a[i][i]); a[j][i]=0; } } for(int i=n;i>1;--i) { for(int j=1;j<i;++j) { a[j][n+1]-=a[i][n+1]*(a[j][i]/a[i][i]); a[j][i]=0; } a[i][n+1]/=a[i][i]; } #ifdef DEBUG cerr<<"after"<<endl; for(int i=1;i<=n;++i){ for(int j=1;j<=n+1;++j) cerr<<a[i][j]<<" "; cerr<<endl;} #endif print(); } int main() { #ifdef COGS freopen("walk.in","r",stdin); freopen("walk.out","w",stdout); #endif pre_work(); gauss(); return 0; }
相关文章推荐
- [BZOJ3143][Hnoi2013][概率与期望][高斯消元]游走
- [BZOJ3143][Hnoi2013]游走(概率期望+高斯消元)
- bzoj3143: [Hnoi2013]游走【概率dp+高斯消元】
- bzoj3143 [Hnoi2013]游走 (期望概率DP + 高斯消元)
- BZOJ 3143: [Hnoi2013]游走 [概率DP 高斯消元]
- bzoj 3143: [Hnoi2013]游走 (概率与期望+高斯消元)
- 【BZOJ-3143】游走 高斯消元 + 概率期望
- 【BZOJ3143】游走,概率计算+高斯消元
- BZOJ.3143.[HNOI2013]游走(概率 期望 高斯消元)
- bzoj 3143: [Hnoi2013]游走(高斯消元)
- 【BZOJ3143】【Hnoi2013】游走 高斯消元 解期望方程
- BZOJ 3143: [Hnoi2013]游走( 高斯消元 )
- BZOJ 3143 游走(高斯消元)
- bzoj 3143 hnoi2013 游走(高斯消元)
- [BZOJ3143][HNOI2013]游走(期望+高斯消元)
- bzoj3143 [Hnoi2013]游走 高斯消元
- BZOJ3143 [Hnoi2013]游走 【高斯消元】
- 【BZOJ 3143】 [Hnoi2013]游走 期望DP|高斯消元|贪心
- BZOJ3143 [Hnoi2013]游走 【高斯消元】
- bzoj 3143: [Hnoi2013]游走 高斯消元