zoukankan      html  css  js  c++  java
  • [luogu3232 HNOI2013] 游走 (高斯消元 期望)

    传送门

    题目描述

    一个无向连通图,顶点从1编号到N,边从1编号到M。 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点的某条边,沿着这条边走到下一个顶点,获得等于这条边的编号的分数。当小Z 到达N号顶点时游走结束,总分为所有获得的分数之和。 现在,请你对这M条边进行编号,使得小Z获得的总分的期望值最小。

    输入输出格式

    输入格式:

    第一行是正整数N和M,分别表示该图的顶点数 和边数,接下来M行每行是整数u,v(1<=u,v<=N),表示顶点u与顶点v之间存在一条边。 输入保证30%的数据满足N<=10,100%的数据满足2<=N<=500且是一个无向简单连通图。

    输出格式:

    仅包含一个实数,表示最小的期望值,保留3位小数。

    输入输出样例

    输入样例#1:

    3 3
    2 3
    1 2
    1 3

    输出样例#1:

    3.333

    说明

    边(1,2)编号为1,边(1,3)编号2,边(2,3)编号为3。

    题解

    思路就是先求出每一条边的概率,然后编号(概率大的编号小)然后乘起来就是期望
    而一条边的期望值等于它所连的两个点到这条边的期望值
    而一个点到一条边的期望值等于这个点的期望值*1/点的度数
    而一个点(u)的期望值是与它所连的所有点(v)的期望值/度数之和
    (f[x]=sum_{i=1}^kfrac{f[i]}{du[i]}) k是x所连所有点的点集
    根据这个每个点列出方程高斯消元即可(注意1和n点)

    code:

    //By Menteur_Hxy
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<map>
    #define LL long long
    #define M(a,b) memset(a,(b),sizeof(a))
    #define F(i,a,b) for(register int i=(a);i<=(b);i++)
    #define C(i,a,b) for(register int i=(b);i>=(a);i--)
    #define E(i,u) for(register int i=head[u];i;i=nxt[i])
    using namespace std;
    
    LL rd() {
        LL x=0,f=1; char c=getchar();
        while(!isdigit(c)) {if(c=='-') f=-f;c=getchar();}
        while(isdigit(c)) x=(x<<1)+(x<<3)+c-48,c=getchar();
        return x*f;
    }
    const int N=510;
    struct edge
    {
        int to,next;
    }e[N*N*2];
    
    int st[N*N*2],n,m,tot,x,y,s[N*N*2],ed[N*N*2];
    double d[N],f[N][N],ans[N],sum,E[N*N*2];
    
    void add(int x,int y)
    {
        e[++tot].to=y;
        e[tot].next=st[x];
        st[x]=tot;
    }
    
    const double eps=1e-11;//之前1e-7结果精度爆炸QAQ
    
    int gauss() {
        int h=1,l=1;n-=1;
        for(;h<=n&&l<=n+1;h++,l++) {
            int r=h;
            F(i,h+1,n) if(fabs(f[r][l])<fabs(f[i][l])) r=i;
            if(fabs(f[r][l])<eps) {h--;continue;}
            if(r!=h) F(i,l,n+1) swap(f[r][i],f[h][i]);
            F(i,h+1,n) if(fabs(f[i][l])>eps) {
                double t=f[i][l]/f[h][l];
                F(j,l,n+1) f[i][j]-=f[h][j]*t;
                f[i][l]=0;
            }
        }
        F(i,h,n) if(fabs(f[i][n+1])>eps) return -1;
        if(h<n+1) return n+1-h;
        C(i,1,n) {
            double tmp=f[i][n+1];
            F(j,i+1,n) tmp-=ans[j]*f[i][j];
            ans[i]=(tmp/f[i][i]);
        }
        n+=1;
        return 0;
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for (int i=1;i<=m;i++)
        {
            scanf("%d%d",&x,&y);
            add(x,y),add(y,x);
            d[x]+=1.0,d[y]+=1.0;
            s[i]=x,ed[i]=y;
        }
        for (int i=1;i<n;i++)
        {
            f[i][i]=1.0;
            for (int j=st[i];j;j=e[j].next)
                if (e[j].to!=n)
                    f[i][e[j].to]=-1/d[e[j].to];
        }
        f[1][n]=1;
        gauss();
        for (int i=1;i<=m;i++)
            E[i]=ans[s[i]]/d[s[i]]+ans[ed[i]]/d[ed[i]];
        sort(E+1,E+m+1);
        for (int i=1;i<=m;i++)
            sum+=E[i]*(m-i+1.0);
        printf("%.3lf",sum);
        return 0;
    }
    
    版权声明:本文为博主原创文章,未经博主允许不得转载。 博主:https://www.cnblogs.com/Menteur-Hxy/
  • 相关阅读:
    使用POI读取excel文件内容
    有序链表
    jQuery Validate验证框架详解
    怎样在VS2010中打开VS2012的项目
    在Win8.1系统下如何安装运行SQL Server 2005
    SQL2005 2008配置错误,无法识别的配置节 system.serviceModel machine.config配置文件有问题
    深入浅出学Spring Data JPA
    Java 学习摘要
    JFinal
    spring 4 + jpa(hibernate 3/4) + spring mvc 多数据源配置
  • 原文地址:https://www.cnblogs.com/Menteur-Hxy/p/9262610.html
Copyright © 2011-2022 走看看