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

    题意

    给定一个 nnn 个点 mmm 条边的无向连通图,顶点从 111 编号到 nnn,边从 111 编号到 mmm。

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

    思路

    因为路径中有环,所以不能直接递推,所以要先把期望的式子列出来,再进行高斯消元求解,求完解后,按期望大小进行排序,期望次数 大的就有小的标号,小的用大的标号,依次后求出答案

    代码

    #include<bits/stdc++.h>
    using namespace std;
    int du[503],num,head[503];
    double b[503],f[250004];
    double g[505][505],x[503];
    struct{
        int ne,to,w;
    }a[250004];
    void lian(int from,int to){
        num++;
        a[num].ne=head[from];
        a[num].to=to;
        head[from]=num;
    }
    void guss(int n){
        int i,j,k,Max;
        double p;
        for(i=1;i<=n;i++){
            Max=i;
            for(j=i+1;j<=n;j++)
                if(fabs(g[Max][i])<fabs(g[j][i]))Max=j;
            for(j=i;j<=n;j++)
                swap(g[i][j],g[Max][j]);
            swap(b[i],b[Max]);
            for(j=1;j<=n;j++)if(i!=j&&g[j][i]!=0){
                p=g[j][i]/g[i][i];b[j]-=b[i]*p;
                for(k=1;k<=n;k++)
                    g[j][k]-=g[i][k]*p;
            }
        }
    }
    int main(){
        int n,m,to,i,j,u,v,w,from;
        double ans=0;
        scanf("%d%d",&n,&m);
        for(i=1;i<=m;i++){
            scanf("%d%d",&u,&v);
            lian(u,v);lian(v,u);
            du[u]++;du[v]++;
        }
        for(i=1;i<n;i++){
            g[i][i]=1;
            for(j=head[i];j;j=a[j].ne){
                to=a[j].to;
                if(to!=n)g[i][to]=-1.0/du[to];
            }
        }b[1]=1;
        guss(n-1);
        for(i=1;i<n;i++){
            if(g[i][i]!=0)x[i]=b[i]/g[i][i];
        //    cout<<du[i]<<" ";
        }
    //    for(i=1;i<=n;i++)
        //    for(j=1;j<=n;j++)cout<<g[i][j]<<" ";
        for(i=2;i<=num;i+=2){
            to=a[i].to;from=a[i-1].to;
            if(to!=n)f[i/2]=x[to]/du[to];
            if(from!=n)f[i/2]+=x[from]/du[from];
        }
        sort(f+1,f+num/2+1);
        for(i=1;i<=num/2;i++)
            ans+=f[i]*(num/2-i+1);
        printf("%.3lf
    ",ans);
        return 0;
    }
  • 相关阅读:
    Linux 动态库剖析
    【jquery mobile笔记二】jquery mobile调用豆瓣api示例
    地标性建筑
    地标性建筑
    翻译的艺术 —— 专有名词(广告词、国外品牌、语言等)
    翻译的艺术 —— 专有名词(广告词、国外品牌、语言等)
    黄金白银、古董与收藏
    黄金白银、古董与收藏
    经典书单 —— 计算机图形学
    经典书单 —— 计算机图形学
  • 原文地址:https://www.cnblogs.com/Jessica-Cao/p/14002138.html
Copyright © 2011-2022 走看看