【BZOJ】3143: [Hnoi2013]游走

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3143


 

显然如果一条边期望被走过的次数越多,我们就应该给它的编号越小。

所以问题变为如何求每一条边被经过的期望次数

考虑直接求边的期望有点困难。

设:${g[i]}$表示经过第$i$条边的期望次数,${f[i]}$表示经过第$i$个点的期望次数,${du[i]}$表示第$i$个点的度数。

对于一条边$i$,假设这条边的两段的点分别为${x,y}$,则${g[i]=\frac{f[x]}{du[x]}*\frac{f[y]}{du[y]}}$

所以问题变为如何求每一个点被经过的期望次数

 

设$e[x][y]$表示点$x,y$之间有连边。这就很裸了,${f[i]=\sum (\frac{f[x]}{du[x]}\left [ e[i][x]=1 \right ] )}$,其中$n$号点只能走进去而不能出来,所以忽略不管,$1$号点应当强制$+1$(因为一开始就从$1$号点开始)

这样就得到了一个$n-1$个未知数和$n-1$个式子的方程组,高斯消元求得每个未知数的解(即${f[i]}$),然后求出${g[i]}$,然后从大到小排序。

$${\sum _{i=1}^{m}g[i]*i}$$


 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<vector>
 5 #include<cstdlib>
 6 #include<cmath>
 7 #include<cstring>
 8 using namespace std;
 9 #define maxn 510
10 #define llg long long 
11 #define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
12 llg n,m;
13 double a[maxn][maxn],du[maxn],f[maxn],g[maxn*maxn];
14 
15 struct Edge{llg x,y;}e[maxn*maxn];
16 
17 bool cmp(double x,double y){return x>y;}
18 
19 void guass()
20 {
21     llg r;
22     for (llg i=1;i<=n;i++)
23     {
24         r=i;
25         for (llg j=i+1;j<=n;j++) if (fabs(a[j][i])>fabs(a[r][i])) r=j;
26         if (r!=i) for (llg j=1;j<=n+1;j++) swap(a[r][j],a[i][j]);
27 
28         for (llg k=i+1;k<=n;k++)
29         {
30             double F=a[k][i]/a[i][i];
31             for (llg j=i;j<=n+1;j++) a[k][j]-=F*a[i][j];
32         }
33     }
34 
35     for (llg i=n;i>=1;i--)
36     {
37         for (llg j=i+1;j<=n;j++) a[i][n+1]-=f[j]*a[i][j];
38         f[i]=a[i][n+1]/a[i][i];
39     }
40 }
41 
42 void init()
43 {
44     llg x,y;
45     cin>>n>>m;
46     for (llg i=1;i<=m;i++)
47     {
48         scanf("%lld%lld",&e[i].x,&e[i].y);
49         du[e[i].x]++,du[e[i].y]++;
50     }
51     for (llg i=1;i<=m;i++)
52     {
53         x=e[i].x,y=e[i].y;
54         if (y!=n) {a[x][y]=1.00/du[y];}
55         if (x!=n) {a[y][x]=1.00/du[x];}
56     }
57     for (llg i=1;i<n;i++) a[i][i]=-1;
58     a[1][n]=-1;
59     n--;
60 }
61 
62 int main()
63 {
64     yyj("walk");
65     init();
66     guass();
67     for (llg i=1;i<=m;i++) g[i]=f[e[i].x]/du[e[i].x]+f[e[i].y]/du[e[i].y];
68     double ans=0;
69     sort(g+1,g+m+1,cmp);
70     for (llg i=1;i<=m;i++) ans+=(double)i*g[i];
71     printf("%.3lf",ans);
72     return 0;
73 }

 

posted @ 2017-02-23 14:20  №〓→龙光←  阅读(200)  评论(0编辑  收藏  举报