• 【HNOI2013】游走


    P2351 - 【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。
    由于搬运者发现官方数据没有程序能跑对最后两个点,遂修改其结果。

    先算出到每个点的期望值f[i]=Σf[to]/deg[to],然后因为1是起点所以f[1]还要加1。
    然后可以发现这个式子的意思就是
    f[i]加上每个可以走到i这个点的期望*走到i的概率,
    因为走到n就不能走了,所以为了消除n对别的点的影响,
    f[n]=0
    其实我推方程半天没推出来就是因为这个f[n]=0,还有f[1]要加1
    然后就可以高斯消元法解方程,这样就可以把点的期望求出来了。
    然后边的期望就是p[i]=p[u]/deg[u]+p[v]/deg[v](u,v是这条边连的两个点)
    然后贪心算答案就可以了。
     1 #include<set>
     2 #include<map>
     3 #include<queue>
     4 #include<stack>
     5 #include<ctime>
     6 #include<cmath>
     7 #include<string>
     8 #include<vector>
     9 #include<cstdio>
    10 #include<cstdlib>
    11 #include<cstring>
    12 #include<iostream>
    13 #include<algorithm>
    14 #define maxn 510
    15 using namespace std;
    16 struct data{
    17   int nex,to;
    18 }e[maxn*maxn*2];
    19 double deg[maxn],a[maxn][maxn],p[maxn*maxn];
    20 int head[maxn],edge=0,n;
    21 void add(int from,int to){
    22   e[++edge].nex=head[from];
    23   e[edge].to=to;
    24   head[from]=edge;
    25 }
    26 void gauss(){
    27   for(int i=1;i<=n;i++){
    28     int t=i;
    29     while(!a[t][i] && t<=n) t++;
    30     if(t>n) continue;
    31     for(int j=1;j<=n+1;j++) swap(a[t][j],a[i][j]);
    32     double k=a[i][i];
    33     for(int j=i;j<=n+1;j++) a[i][j]/=k;
    34     for(int j=1;j<=n;j++)
    35       if(j!=i && a[j][i]){
    36     k=a[j][i];
    37     for(int p=i;p<=n+1;p++)
    38       a[j][p]-=k*a[i][p];
    39       }
    40   }
    41 }
    42 bool cmp(const double &a,const double &b){
    43   return a>b;
    44 }
    45 int main()
    46 {
    47   freopen("walk.in","r",stdin);
    48   freopen("walk.out","w",stdout);
    49   int m,x,y;
    50   scanf("%d%d",&n,&m);
    51   for(int i=1;i<=m;i++){
    52     scanf("%d%d",&x,&y);
    53     add(x,y),add(y,x),deg[x]++,deg[y]++;
    54   }
    55   for(int i=1;i<n;i++){
    56     if(i==1) a[i][n+1]=1;
    57     a[i][i]=1;
    58     for(int j=head[i];j;j=e[j].nex)
    59       a[i][e[j].to]-=1/deg[e[j].to];
    60   }
    61   a[n][n]=0;
    62   gauss();
    63   for(int i=1;i<=edge;i+=2)
    64     p[(i+1)/2]=(a[e[i].to][n+1]/deg[e[i].to])+(a[e[i+1].to][n+1]/deg[e[i+1].to]);
    65   sort(p+1,p+m+1,cmp);
    66   double ans=0.0;
    67   for(int i=1;i<=m;i++)
    68     ans+=p[i]*i;
    69   printf("%.3lf",ans);
    70   return 0;
    71 }
    
    
    


  • 相关阅读:
    WPF:DataGrid 自动生成行号
    C#:WinForm之Command
    i.MX RT1010之FlexIO模拟SSI外设
    i.MX RT1010之FlexIO模拟I2S外设
    i.MX RT600之DSP开发环境调试篇
    i.MX RT600之DSP调试环境搭建篇
    i.MX RT600之DMIC外设介绍及应用
    i.MX RT600之I2S外设介绍及应用
    ssm框架思维-登录
    idea里面搭建SSM框架-crud
  • 原文地址:https://www.cnblogs.com/pantakill/p/6679637.html
Copyright © 2020-2023  润新知