zoukankan      html  css  js  c++  java
  • 【BZOJ-3143】游走 高斯消元 + 概率期望

    3143: [Hnoi2013]游走

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 2264  Solved: 987
    [Submit][Status][Discuss]

    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。

    Source

    非官方数据

    Solution

    和 博物馆 那道题类似,列期望方程高斯消元得解。

    如果对边进行处理,复杂度是$O((N^{2})^{3})$的,所以考虑利用点来求解边。

    设未知数$X_{i}$表示第$i$号点的期望经过次数。那么显然有$X_{i}=sum X_{j}$这样就可以列方程了。

    显然有两个特例,必然从$1$号点出发,所以$X_{1}-1=sum X_{j}$,以及必然从$N$号点结束,所以$X_{N}=0$,其余的可以得解。

    对于一条边$<u,v>$,经过这条边的期望次数就是$frac {X_{u}} {d[u]}+frac {X_{v}}{d[v]}$,总期望最小,就是期望次数越小的边标号越大即可。

    Code

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    inline int read()
    {
        int x=0,f=1; char ch=getchar();
        while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
        while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    #define MAXN 550
    #define eps 1e-5
    int N,M,mp[MAXN][MAXN],flag,d[MAXN];
    double a[MAXN][MAXN],X[MAXN],p[MAXN*MAXN],ans;
    inline void Debug()
    {
        puts("=========");
        for (int i=1; i<=N; i++,puts(""))
            for (int j=1; j<=N+1; j++) printf("%.2lf ",a[i][j]);
        puts("");
    }
    inline void Gauss()
    {
        flag=1;
        for (int i=1; i<=N; i++)
            {
                int mx=i;
                for (int j=i+1; j<=N; j++)
                    if (abs(a[j][i])>abs(a[mx][i])) mx=j;
                swap(a[i],a[mx]);
                if (abs(a[i][i])<eps) {flag=-1; continue;}
                for (int j=i+1; j<=N+1; j++) if (abs(a[i][j])>0) a[i][j]/=a[i][i];
                a[i][i]=1.0;
                         
                for (int j=i+1; j<=N; j++)
                    {
                        for (int k=i+1; k<=N+1; k++) 
                            a[j][k]-=a[j][i]*a[i][k];
                        a[j][i]=0.0;
                    }
    //            Debug();
            }
        for (int i=1,f=1; i<=N; i++,f=1)
            {
                for (int j=1; j<=N && f; j++)
                    if (abs(a[i][j])>eps) f=0;
                if (abs(a[i][M+1])>eps && f) flag=0;
            }
        if (flag==0) return;
        for (int i=N; i>=1; i--)
            {
                X[i]=a[i][N+1];
                for (int j=i+1; j<=N; j++) X[i]-=X[j]*a[i][j];
            }
    }
    int main()
    {
        N=read(),M=read();
        for (int i=1,x,y; i<=M; i++) x=read(),y=read(),mp[x][y]=mp[y][x]=1,d[x]++,d[y]++; 
        for (int i=1; i<=N-1; i++)
            for (int j=1; j<=N-1; j++)
                if (mp[i][j]) a[i][j]=-1.0/d[j];
        a[1][N+1]=1.0;
        for (int i=1; i<=N; i++) a[i][i]=1.0;
    //  Debug();
        Gauss();
        for (int i=1,tot=0; i<=N; i++)
            for (int j=i+1; j<=N; j++)
                if (mp[i][j]) p[++tot]=X[i]/d[i]+X[j]/d[j];
        sort(p+1,p+M+1);
    //  for (int i=1; i<=M; i++) printf("%.2lf  ",p[i]); puts("");
        for (int i=1; i<=M; i++) ans+=p[i]*(M-i+1);
        printf("%.3lf
    ",ans);
        return 0;
    }
  • 相关阅读:
    微服务框架核心问题
    django restframework 全局异常处理,编写自定义custom_exception_handler
    django 异常处理中间件
    drf_yasg2 定制swagger
    redis-django
    django 权限
    django restframework 多对多的批量修改,基于逻辑删
    python3 动态绑定
    Django restframework 逻辑删除
    django restframework 多对多模型
  • 原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/6133226.html
Copyright © 2011-2022 走看看