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
Sample Output
3.333
HINT
边(1,2)编号为1,边(1,3)编号2,边(2,3)编号为3。
Solution
Code
1 #include2 #include 3 #include 4 #include 5 #include 6 #define N (500+10) 7 using namespace std; 8 9 int Ind[N],head[N],num_edge;10 int n,m,u,v,h,dis[N][N];11 double ans[N],f[N][N],q[N*N];12 13 void Gauss()14 {15 for (int i=1; i<=n; ++i)16 {17 int num=i;18 for (int j=i+1; j<=n; ++j)19 if (fabs(f[j][i])>fabs(f[num][i])) num=j;20 if (num!=i) swap(f[i],f[num]);21 for (int j=i+1; j<=n; ++j)22 {23 double t=f[j][i]/f[i][i];24 for (int k=i; k<=n+1; ++k)25 f[j][k]-=t*f[i][k];26 }27 }28 for (int i=n; i>=1; --i)29 {30 for (int j=i+1; j<=n; ++j)31 f[i][n+1]-=f[i][j]*ans[j];32 ans[i]=f[i][n+1]/f[i][i];33 }34 }35 36 int main()37 {38 scanf("%d%d",&n,&m);39 for (int i=1; i<=m; ++i)40 {41 scanf("%d%d",&u,&v);42 dis[u][v]=dis[v][u]=1;43 Ind[u]++; Ind[v]++;44 }45 for (int i=1; i<=n; ++i)46 {47 f[i][i]=-1;48 for (int j=1; j<=n; ++j)49 if (dis[i][j]) f[i][j]=(double)1/Ind[j];50 }51 f[1][n+1]=-1;52 for (int i=1; i