3143: [Hnoi2013]游走

数组开小引发的惨案…
这题算边的期望转化为算点的期望.
令p[i][j]表示i点到j点的概率
e[i]表示到第i个点的期望
d[i]表示到第i条边的期望
d[i]=e[u[i]]1out[u[i]]+e[v[i]]1out[v[i]] d [ i ] = e [ u [ i ] ] ∗ 1 o u t [ u [ i ] ] + e [ v [ i ] ] ∗ 1 o u t [ v [ i ] ]
ni=1(p[i][j]e[i])=e[j] ∑ i = 1 n ( p [ i ] [ j ] ∗ e [ i ] ) = e [ j ]
其中当 j=1 j = 1 时,有 1+ni=1(p[i][1]e[i])=e[1] 1 + ∑ i = 1 n ( p [ i ] [ 1 ] ∗ e [ i ] ) = e [ 1 ]
要注意到n的时候就会停下来,所以 ni=1[p[n][i]==0]=0 ∑ i = 1 n [ p [ n ] [ i ] == 0 ] = 0
然后高斯消元即可
c++代码如下:

#include<bits/stdc++.h>
#define eps 1e-9
#define rep(i,x,y) for(register int i = x ; i <= y;++ i)
#define repd(i,x,y) for(register int i = x ;i >= y; -- i) 
using namespace std;
typedef long long ll;
template<typename T>inline void read(T&x)
{
    x = 0;char c;int sign = 1;
    do { c = getchar(); if(c == '-') sign = -1; }while(!isdigit(c));
    do { x = x * 10 + c - '0'; c = getchar(); }while(isdigit(c));
    x *= sign;
}

const int N = 505;
long double a[N][N],e[N],f[N*N],ans;
int n,m,size[N];
struct Edge { int u,v; }edge[N*N];

int main()
{
    read(n); read(m);
    rep(i,1,m)
    {
        read(edge[i].u); read(edge[i].v);
        ++ size[edge[i].u]; ++ size[edge[i].v];
    }

    a[1][n + 1] = -1;
    rep(i,1,n) a[i][i] = -1;
    rep(i,1,m)
    {
        if(edge[i].u != n) a[edge[i].u][edge[i].v] += 1.0/size[edge[i].v];
        if(edge[i].v != n) a[edge[i].v][edge[i].u] += 1.0/size[edge[i].u];
    }

    rep(i,1,n)
    {
        rep(j,i + 1,n)
            if(abs(a[i][i]) < abs(a[j][i]))
                swap(a[i],a[j]);

        if(abs(a[i][i]) < eps) continue;

        rep(j,i + 1,n)
        {
            double c = a[j][i]/a[i][i];
            rep(k,i,n + 1)
                a[j][k] -= a[i][k] * c;
        }

    }

    repd(i,n,1)
    {
        rep(j,i + 1,n)
            a[i][n + 1] -= a[i][j]*e[j];
        if(abs(a[i][i]) > eps) e[i] = a[i][n + 1] / a[i][i];
    }

    rep(i,1,m)
    {
        if(edge[i].u != n && size[edge[i].u]) f[i] += e[edge[i].u]/size[edge[i].u];
        if(edge[i].v != n && size[edge[i].v]) f[i] += e[edge[i].v]/size[edge[i].v];
    }
    sort(f + 1,f + 1 + m);

    rep(i,1,m) ans += f[m-i+1] * i;
    cout << fixed << setprecision(3) << ans << endl;

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值