• [bzoj3143][Hnoi2013]游走


    来自FallDream的博客,未经允许,请勿转载,谢谢。


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

    n<=500

    用Si表示到达第i个点的期望次数,显然Si可以表达成其它的一些S的和(一号点给它加1)

    然后上高斯消元 消出Si,每条边的期望次数易求 排序之后标号即可

    理论复杂度n^3+mlogm 但是跑的飞快

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #define MN 500
    #define ld long double
    #define eps 1e-13
    #define getchar() (*SS++)
    char B[1<<26],*SS=B; 
    using namespace std;
    inline int read()
    {
        int x = 0; char ch = getchar();
        while(ch < '0' || ch > '9') ch = getchar();
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x;
    }
    
    int n,m,head[MN+5],cnt=0,d[MN+5],cc=0;
    ld s[MN+5][MN+5],ex[MN+5],S[MN*MN*2],ans=0;
    struct edge{int to,next;}e[MN*MN*2];
    
    inline void ins(int f,int t){e[++cnt]=(edge){t,head[f]};head[f]=cnt;++d[f];}
    
    void Gauss()
    {
        register int i,j;
        for(i=1;i<=n;++i)
        {
            for(j=i;j<=n;++j)
                if(fabs(s[j][i])>eps)
                {
                    if(j!=i)
                    {
                        for(int k=i;k<=n+1;++k)
                            swap(s[j][k],s[i][k]);    
                    }
                    break;
                }
            for(j=i+1;j<=n;++j) if(fabs(s[j][i])>eps)
            {
                ld change=s[j][i]/s[i][i]; 
                for(register int k=i;k<=n+1;++k)
                    s[j][k]=s[j][k]-s[i][k]*change;
            } 
        }
        for(int i=n;i;--i)
        {
            ld k=s[i][n+1];
            for(int j=i+1;j<=n;++j)    k-=ex[j]*s[i][j];
            ex[i]=k/s[i][i];
        }
    }
    
    int main()
    {
        fread(B,1,1<<26,stdin);
        n=read();m=read();
        for(register int i=1;i<=m;i++) 
        {
            int x=read(),y=read();
            ins(x,y);ins(y,x);    
        }     
        for(register int i=1;i<n;s[i][i]=-1,++i)
            for(register int j=head[i];j;j=e[j].next)
                s[e[j].to][i]=(ld)1/d[i];
        s[n][n]=-1;
        s[1][n+1]=-1;
        Gauss();ex[n]=0;
        for(register int i=1;i<=n;++i)
            for(register int j=head[i];j;j=e[j].next)
                if(j&1) S[++cc]=ex[i]/d[i]+ex[e[j].to]/d[e[j].to];    
        sort(S+1,S+cc+1,greater<ld>());
        for(int i=1;i<=cc;++i)
            ans+=S[i]*i;
        printf("%0.3lf
    ",(double)ans);
        return 0;
    }
  • 相关阅读:
    MapReduce job在JobTracker初始化源码级分析
    Flume-NG源码阅读之FileChannel
    linux下gzip压缩同样内容大小不一样
    mapreduce job提交流程源码级分析(三)
    JobTracker启动流程源码级分析
    机器学习经典算法之K-Means
    机器学习经典算法之KNN
    机器学习经典算法之SVM
    机器学习经典算法之朴素贝叶斯分类
    机器学习经典算法之决策树
  • 原文地址:https://www.cnblogs.com/FallDream/p/bzoj3143.html
Copyright © 2020-2023  润新知