其他分享
首页 > 其他分享> > [HNOI2013] 游走 - 概率期望,高斯消元,贪心

[HNOI2013] 游走 - 概率期望,高斯消元,贪心

作者:互联网

假如我们知道了每条边经过的期望次数,则变成了一个显然的贪心。现在考虑如何求期望次数。
由于走到每个点后各向等概率,很显然一条边的期望次数可以与它的两个端点的期望次数,转化为求点的期望次数
考虑每个点对另个点的贡献,得到方程组,暴力高斯消元
注意走到最后一个点就结束了,所以相当于它不能有出边

#include <bits/stdc++.h>
#define eps 1e-6
using namespace std;

const int N = 1005;

double a[N][N];
int n,m,d[N],g[N][N],t1,t2;

bool gauss_jordan()
{
    for(int i=1; i<=n; i++)
    {
        int r=i;
        for(int j=i+1; j<=n; j++)
            if(fabs(a[j][i])>fabs(a[r][i]))
                r=j;
        if(r-i)
            for(int j=1; j<=n+1; j++)
                swap(a[i][j],a[r][j]);
        if(fabs(a[i][i])<eps)
            return 0;
        for(int j=1; j<=n; j++)
            if(j-i)
            {
                double tmp=a[j][i]/a[i][i];
                for(int k=i+1; k<=n+1; k++)
                    a[j][k]-=a[i][k]*tmp;
            }
    }
    for(int i=1; i<=n; i++)
        a[i][n+1]/=a[i][i];
    return 1;
}

vector <pair<int,int> > E;
double res[N*N];

int main()
{
    ios::sync_with_stdio(false);
    cin>>n>>m;
    for(int i=1;i<=m;i++) {
        cin>>t1>>t2;
        g[t1][t2]=1;
        g[t2][t1]=1;
        d[t1]++;
        d[t2]++;
        E.push_back(make_pair(t1,t2));
    }
    a[1][n+1]=1;
    a[n][n]=1;
    for(int i=1;i<n;i++) {
        a[i][i]=1;
        for(int j=1;j<=n;j++)
            if(g[j][i])
                a[i][j] -= 1.0/d[j];
    }
    gauss_jordan();

    double ans = 0;
    for(int i=0;i<m;i++)
        res[i]=a[E[i].first][n+1]/d[E[i].first] + a[E[i].second][n+1]/d[E[i].second];
    sort(res,res+m);
    for(int i=0;i<m;i++) ans+=res[i]*(m-i);
    printf("%.3f\n",ans);
}

标签:期望,int,t2,t1,HNOI2013,次数,高斯消,贪心
来源: https://www.cnblogs.com/mollnn/p/11677020.html