卧槽这题BZOJ上的数据用了dcmp就会WA不讲道理。。。裸的才能A。。。
除了第一个点以外,每个点到达的期望次数是与它相连的点的期望次数除以度数之和,一条边的期望次数是他非n端点(因为到n就不再走出来了)的期望次数除以度数之和,
排序后赋值即可。
#include<cstdlib> #include<cstdio> #include<iostream> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<queue> #define maxn 500005 #define oo 999999999 using namespace std; int n,m; int g[505][505]; double G[505][505]; struct data { int x,y; double n; }E[250005]; bool cmp(data x,data y) { return x.n>y.n; } void Debug() { for(int i=1;i<=n;i++) { for(int j=1;j<=n+1;j++) { printf("%.3lf ",G[i][j]); } putchar('\n'); } putchar('\n'); return ; } void Init() { scanf("%d%d",&n,&m); memset(g,0,sizeof(g)); int x,y; for(int i=1;i<=m;i++) { scanf("%d%d",&x,&y); E[i].x=x; E[i].y=y; g[x][y]=g[y][x]=1; g[x][0]++; g[y][0]++; } for(int i=1;i<=n;i++) { G[i][i]=1.0;if(i==1)G[i][n+1]=1.0; for(int j=1;j<n;j++)if(g[i][j]) { G[i][j]=-(1.0)/(double)g[j][0]; } } //Debug(); return ; } double Abs(double x) { return x<0 ? -x : x; } double f,eps=0.00000000001; void Gauss() { int ni=1,nj=1,r; while(ni<=n && nj<= n) { r=ni; for(int i=ni+1;i<=n;i++) { if(Abs(G[i][nj])>Abs(G[r][nj])) { r=i; } } if(Abs(G[r][nj])>=eps) { for(int i=1;i<=n+1;i++) { swap(G[r][i],G[ni][i]); } for(int i=1;i<=n;i++)if(i!=ni) { f=G[i][nj]/G[ni][nj]; for(int j=1;j<=n+1;j++) { G[i][j]-=G[ni][j]*f; } } ni++; } nj++; } for(int i=1;i<=n;i++) { G[i][n+1]=G[i][n+1]/G[i][i]; G[i][i]=1.0; } //Debug(); return ; } int main() { //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); Init(); Gauss(); int x,y; for(int i=1;i<=m;i++) { x=E[i].x; y=E[i].y; E[i].n=0.0; if(x!=n && g[x][0]!=0) { E[i].n+=G[x][n+1]/(double)g[x][0]; } if(y!=n && g[y][0]!=0) { E[i].n+=G[y][n+1]/(double)g[y][0]; } } sort(E+1,E+1+m,cmp); double ans=0; for(int i=1;i<=m;i++) { ans+=E[i].n*(double)(i); } printf("%.3lf\n",ans+eps); return 0; }