• 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

    Solution

    Code

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<cmath>
     5 #include<algorithm>
     6 #define N (500+10)
     7 using namespace std;
     8 
     9 int Ind[N],head[N],num_edge;
    10 int n,m,u,v,h,dis[N][N];
    11 double ans[N],f[N][N],q[N*N];
    12 
    13 void Gauss()
    14 {
    15     for (int i=1; i<=n; ++i)
    16     {
    17         int num=i;
    18         for (int j=i+1; j<=n; ++j)
    19             if (fabs(f[j][i])>fabs(f[num][i])) num=j;
    20         if (num!=i) swap(f[i],f[num]);
    21         for (int j=i+1; j<=n; ++j)
    22         {
    23             double t=f[j][i]/f[i][i];
    24             for (int k=i; k<=n+1; ++k)
    25                 f[j][k]-=t*f[i][k];
    26         }
    27     }
    28     for (int i=n; i>=1; --i)
    29     {
    30         for (int j=i+1; j<=n; ++j)
    31             f[i][n+1]-=f[i][j]*ans[j];
    32         ans[i]=f[i][n+1]/f[i][i];
    33     }
    34 }
    35 
    36 int main()
    37 {
    38     scanf("%d%d",&n,&m);
    39     for (int i=1; i<=m; ++i)
    40     {
    41         scanf("%d%d",&u,&v);
    42         dis[u][v]=dis[v][u]=1;
    43         Ind[u]++; Ind[v]++;
    44     }
    45     for (int i=1; i<=n; ++i)
    46     {
    47         f[i][i]=-1;
    48         for (int j=1; j<=n; ++j)
    49             if (dis[i][j]) f[i][j]=(double)1/Ind[j];
    50     }
    51     f[1][n+1]=-1;
    52     for (int i=1; i<n; ++i) f[n][i]=0;
    53     Gauss();
    54     for (int i=1; i<=n; ++i)
    55         for (int j=i+1; j<=n; ++j)
    56             if (dis[i][j])
    57                 q[++h]=ans[i]/Ind[i]+ans[j]/Ind[j];
    58     sort(q+1,q+h+1);
    59     double Ans=0;
    60     for (int i=1; i<=m; ++i)
    61         Ans+=i*q[m-i+1];
    62     printf("%.3lf
    ",Ans);
    63 }
  • 相关阅读:
    ububtu 14.04 问题集合
    ubuntu grub 引导修复
    Ubuntu 下 glpk 的安装及使用
    ubuntu vim 7.4 编译安装
    ubuntu 12.04 clang 3.4 安装
    CMakeLists实战解读--YouCompleteMe
    Flume安装及部署
    SpringBoot整合kafka
    linux安装kafka
    Linux安装zookeeper
  • 原文地址:https://www.cnblogs.com/refun/p/8963943.html
Copyright © 2020-2023  润新知