zoukankan      html  css  js  c++  java
  • [HNOI2013] 游走

    题意:

    一张无向图,从点1开始随机游走,走到点n时结束。每走一条边会得到等同于边权的收益。

    (随机游走:每次等概率选择一条当前点的出边走过去)

    请你给m条边分配边权(边权是1-m的排列),使得期望收益最小。

    $nleq 500$。

    题解:

    令期望收益为S,边$(u,v)$的边权为$w_{u,v}$,期望经过次数为$cnt_{u,v}$,则有$S=sum cnt_{u,v} imes w_{u,v}$。

    发现$cnt_{u,v}$并不好求,但如果知道了每个点u的期望经过次数$F_u$和度数$D_u$,就有$cnt_{u,v}=frac{F_u }{D_u }+frac{F_v }{D_v }$。

    而$F_1 =1+sum frac{F_v }{D_v },F_u =sum frac{F_v }{D_v }$,于是可以用高斯消元解出所有的F,然后反推cnt,倒序分配边权即可。

    注意点n是不能走出去的,所以列方程时需要特判。

    复杂度$O(n^{3})$。

    套路:

    • 求边经过次数$ ightarrow$求点经过次数。
    • 随机游走问题:在列方程时注意终点是不能往外走的。

    代码:

    #include<bits/stdc++.h>
    #define maxn 505
    #define maxm 500005
    #define inf 0x7fffffff
    #define ll long long
    #define rint register int
    #define debug(x) cerr<<#x<<": "<<x<<endl
    #define fgx cerr<<"--------------"<<endl
    #define dgx cerr<<"=============="<<endl
    
    using namespace std;
    int D[maxm],G[maxn][maxn];
    double A[maxn][maxn],res[maxm],F[maxm];
    
    inline int read(){
        int x=0,f=1; char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    
    inline void Gauss(int n){
        for(int j=1;j<=n;j++){
            for(int i=j;i<=n;i++)
                if(A[i][j]!=0){
                    for(int k=1;k<=n+1;k++) swap(A[i][k],A[j][k]);
                    break;
                }
            if(A[j][j]==0) continue;
            for(int i=1;i<=n;i++)
                if(i!=j && A[i][j]!=0){
                    double x=A[i][j]/A[j][j];
                    for(int k=1;k<=n+1;k++) A[i][k]-=A[j][k]*x;
                }
        }
    }
    
    int main(){
        int n=read(),m=read(),tot=0;
        for(int i=1;i<=m;i++){
            int u=read(),v=read();
            G[u][v]=G[v][u]=1,D[u]++,D[v]++;
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                if(i==j) A[i][j]=1;
                else if(j==n) A[i][j]=0;
                else if(G[i][j]) A[i][j]=-1.0/(D[j]+0.0);
                else A[i][j]=0;
            }
            A[i][n+1]=(i==1)?1:0;
        }
        Gauss(n);
        for(int i=1;i<=n;i++) F[i]=A[i][n+1]/A[i][i];
        for(int i=1;i<=n;i++)
            for(int j=i+1;j<=n;j++){
                if(!G[i][j]) continue;
                if(j==n) res[++tot]=F[i]/(D[i]+0.0);
                else res[++tot]=F[i]/(D[i]+0.0)+F[j]/(D[j]+0.0);
            }
        sort(res+1,res+1+tot);
        double ans=0;
        for(int i=1;i<=m;i++) ans+=res[i]*(m-i+1);
        printf("%.3lf
    ",ans);
        return 0;
    }
    游走
  • 相关阅读:
    Swagger2 添加HTTP head参数
    获取枚举类型描述
    JS设置cookie、读取cookie、删除cookie
    ES6中Promise的入门(结合例子)
    阮一峰的ES6---Promise对象
    model_util.py
    IfcSpatialElementType
    labelme coco
    python opencv KeyPoint
    IfcSpatialZoneType
  • 原文地址:https://www.cnblogs.com/YSFAC/p/13227793.html
Copyright © 2011-2022 走看看