首页 > 代码库 > bzoj 3143: [Hnoi2013]游走 高斯消元
bzoj 3143: [Hnoi2013]游走 高斯消元
3143: [Hnoi2013]游走
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1026 Solved: 448
[Submit][Status]
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 3
2 3
1 2
1 3
2 3
1 2
1 3
Sample Output
3.333
HINT
边(1,2)编号为1,边(1,3)编号2,边(2,3)编号为3。
这道题我又把题目看错了,我最开始看成了有向无环图,【目测世纪大水题】。。。
当这种期望题出现环之后,就变的复杂很多,我们可以对于每一个点求出它的期望经过次数p[],则p[i]=segma(p[j]/d[j]),有一点还是有点不清楚,就是为什么p[1]在上述式子上必须恰好加1,就只好姑且先记住这样的结论吧。
有了上述思路,就可以用高斯消元来做了。
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define MAXN 1000#define MAXV MAXN#define MAXE 500000#define abs(x) ((x)>0?(x):(-(x)))typedef long double real;struct Edge{ int np; Edge *next;}E[MAXE],*V[MAXV];int tope=-1;void addedge(int x,int y){ E[++tope].next=V[x]; E[tope].np=y; V[x]=&E[tope];}int deg[MAXN];int q[MAXN];real pp[MAXN];real a[MAXN][MAXN];int n,m;struct edge{ int x,y; real p;}w[MAXE];bool cmp_p(edge e1,edge e2){ return e1.p>e2.p;}void pm(){ for (int i=1;i<n;i++) { for (int j=1;j<=n;j++) { printf("%.2Lf ",a[i][j]); } printf("\n"); } printf("\n");}int main(){ freopen("input.txt","r",stdin); int i,j,k,x,y,z; scanf("%d%d",&n,&m); for (i=0;i<m;i++) { scanf("%d%d",&x,&y); addedge(x,y); addedge(y,x); deg[x]++;deg[y]++; w[i].x=x;w[i].y=y; } int now; Edge *ne; for (i=1;i<=n-1;i++) { now=i; for (ne=V[now];ne;ne=ne->next) { if (ne->np!=n) a[now][ne->np]=1.0/deg[ne->np]; } a[now][now]=-1; a[now][n]=0; } a[1][n]=1; //pm(); for (i=1;i<=n-1;i++) { x=i; for (j=i+1;j<=n-1;j++) { if (abs(a[j][i])>abs(a[x][i])) { x=j; } } if (x!=i) { for (j=i;j<=n;j++) { swap(a[i][j],a[x][j]); } } if (!a[i][i])continue; for (j=i+1;j<=n-1;j++) { real t=a[j][i]/a[i][i]; for (k=i;k<=n;k++) { a[j][k]-=t*a[i][k]; } } //pm(); } pp[n]=1; for (i=n-1;i>=1;i--) { for (j=i+1;j<=n;j++) { pp[i]-=pp[j]*a[i][j]; } pp[i]/=a[i][i]; } pp[n]=0;/* for (i=1;i<=n;i++) printf("%.2Lf ",pp[i]); printf("\n");*/ for (i=0;i<m;i++) { w[i].p=pp[w[i].x]/deg[w[i].x] + pp[w[i].y]/deg[w[i].y]; } sort(w,w+m,cmp_p); int head=-1,tail=-1; real ans=0; for (i=0;i<m;i++) { ans+=(i+1)*w[i].p; } printf("%.3Lf",ans);}
bzoj 3143: [Hnoi2013]游走 高斯消元
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。