3143. [HNOI2013]游走【高斯消元】

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

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<cmath>
 5 #include<algorithm>
 6 #define N (500+10)
 7 using namespace std;
 8 
 9 double eps=1e-10;
10 int dcmp(double x){if (fabs(x)<eps)return 0; return x>0?1:-1;}
11 
12 int Ind[N],head[N],num_edge;
13 int n,m,u,v,h,dis[N][N];
14 double ans[N],f[N][N],q[N*N];
15 
16 void Gauss()
17 {
18     for (int i=1; i<=n; ++i)
19     {
20         int num=i;
21         for (int j=i+1; j<=n; ++j)
22             if (dcmp(fabs(f[j][i])-fabs(f[num][i]))>0) num=j;
23         if (num!=i) for (int j=1; j<=n+1; ++j) swap(f[i][j],f[num][j]);
24         
25         for (int j=i+1; j<=n+1; ++j)
26             if (dcmp(f[j][i]))
27             {
28                 double t=f[j][i]/f[i][i];
29                 for (int k=i; k<=n+1; ++k)
30                     f[j][k]-=f[i][k]*t;
31             }
32     }
33     for (int i=n; i>=1; --i)
34     {
35         for (int j=i+1; j<=n; ++j) f[i][n+1]-=f[i][j]*ans[j];
36         ans[i]=f[i][n+1]/f[i][i];
37     }
38 }
39 
40 int main()
41 {
42     scanf("%d%d",&n,&m);
43     for (int i=1; i<=m; ++i)
44     {
45         scanf("%d%d",&u,&v);
46         dis[u][v]=dis[v][u]=1;
47         Ind[u]++; Ind[v]++;
48     }
49     for (int i=1; i<=n; ++i)
50     {
51         f[i][i]=-1;
52         for (int j=1; j<=n; ++j)
53             if (dis[i][j])
54                 f[i][j]=(double)1/Ind[j];
55     }
56     f[1][n+1]=-1;
57     for (int i=1; i<n; ++i) f[n][i]=0;
58     Gauss();
59     for (int i=1; i<=n; ++i)
60         for (int j=i+1; j<=n; ++j)
61             if (dis[i][j])
62                 q[++h]=ans[i]/Ind[i]+ans[j]/Ind[j];
63     sort(q+1,q+h+1);
64     double Ans=0;
65     for (int i=1; i<=m; ++i)
66         Ans+=i*q[m-i+1];
67     printf("%.3lf",Ans);
68 }

猜你喜欢

转载自www.cnblogs.com/refun/p/8963943.html