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

    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。

    权当复习高斯消元喽
    如果我们能求出每条边被经过的期望次数,那么只要从大到小标号就好了
    而求边是比较难的,相对的求点更简单。。。
    而一条边被经过的次数可以由两个端点算出
    现在只需要求点即可,我们发现每个点的期望都跟所有跟他相邻的点有关
    也就是说我们能列出n个方程,接下来就要用高斯消元来处理
    f就是那个矩阵,因为n比较特殊所以就作为存等式右边的一列,n*(n-1)
    首先1号点在开始时必须被经过1次,f[1][n]+=1
    然后在各项填上系数,使得f[i][n]=0
    之后就是消元
    在这里是将f[j][i]绝对值最大的那一行换到第i行上
    接下来再把f[i][i]调整成1,在所有第i列上不为0的行上消去第i列
    这样做结束后直接f[i][n]就是i的答案
    最后统计边,标号,输出答案
     1 #include<algorithm>
     2 #include<cstdio>
     3 #include<cmath>
     4 #define N 505
     5 #define eps 1e-8
     6 using namespace std;
     7 int n,m;
     8 int to[N*N*2],nxt[N*N*2],h[N],etop;
     9 int F[N*N],T[N*N];
    10 double q[N*N];
    11 int num[N];
    12 double f[N][N];
    13 double im[N*N*2];
    14 void add(int u,int v){
    15     num[u]++;to[++etop]=v;
    16     nxt[etop]=h[u];h[u]=etop;
    17 }
    18 int main(){
    19     scanf("%d%d",&n,&m);
    20     for(int i=1,u,v;i<=m;i++){
    21         scanf("%d%d",&u,&v);
    22         add(u,v);add(v,u);
    23         F[i]=u;T[i]=v;
    24     }
    25     f[1][n]=1;
    26     for(int i=1;i<n;i++){
    27         f[i][i]=1;
    28         for(int j=h[i];j;j=nxt[j])
    29             if(to[j]!=n)
    30                 f[i][to[j]]=-1.0/num[to[j]];
    31     }
    32     for(int i=1;i<n;i++){
    33         int now=i;
    34         double s=f[i][i];
    35         for(int j=i+1;j<n;j++)
    36             if(fabs(f[j][i])-fabs(s)>eps){now=j;s=f[j][i];}
    37         if(now!=i){
    38             for(int j=1;j<n;j++)
    39                 swap(f[i][j],f[now][j]);
    40         }
    41         for(int j=n;j>=i;j--)f[i][j]/=f[i][i];
    42         for(int j=1;j<n;j++)
    43             if(i!=j)
    44                 for(int k=n;k>=i;k--)
    45                     f[j][k]-=f[j][i]*f[i][k];
    46     }
    47     for(int i=1;i<=m;i++){
    48         if(F[i]!=n)
    49             q[i]+=f[F[i]][n]*(1.0/num[F[i]]);
    50         if(T[i]!=n)
    51             q[i]+=f[T[i]][n]*(1.0/num[T[i]]);
    52     }
    53     sort(q+1,q+1+m);
    54     double ans=0;
    55     for(int i=1;i<=m;i++)
    56         ans+=q[i]*((m-i+1)*1.0);
    57     printf("%.3lf",ans);
    58     return 0;
    59 }
    View Code
  • 相关阅读:
    Docker03-镜像
    Docker02:Centos7.6安装Docker
    Docker01-重要概念
    WEB开发新人指南
    Lpad()和Rpad()函数
    Unable to find the requested .Net Framework Data Provider. It may not be installed
    redis自动过期
    redis简单的读写
    redis的安装
    Ajax缓存,减少后台服务器压力
  • 原文地址:https://www.cnblogs.com/2017SSY/p/10250131.html
Copyright © 2011-2022 走看看