BZOJ 3143: [Hnoi2013]游走

3143: [Hnoi2013]游走

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 2429  Solved: 1049
[Submit][Status][Discuss]

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。

 

Source

[Submit][Status][Discuss]

 

 

先求出每个点的期望经过次数,则每条边的经过次数为x点出发,走这条边的期望+y点出发,走这条边的概率。

 

  1 #include <bits/stdc++.h>
  2 
  3 inline char nextChar(void)
  4 {
  5     static const int siz = 1024;
  6     
  7     static char buf[siz];
  8     static char *hd = buf + siz;
  9     static char *tl = buf + siz;
 10     
 11     if (hd == tl)
 12         fread(hd = buf, 1, siz, stdin);
 13     
 14     return *hd++;
 15 }
 16 
 17 inline int nextInt(void)
 18 {
 19     register int ret = 0;
 20     register int neg = false;
 21     register int bit = nextChar();
 22     
 23     for (; bit < 48; bit = nextChar())
 24         if (bit == '-')neg ^= true;
 25         
 26     for (; bit > 47; bit = nextChar())
 27         ret = ret * 10 + bit - 48;
 28         
 29     return neg ? -ret : ret;
 30 }
 31 
 32 int n, m;
 33 
 34 struct edge
 35 {
 36     int x, y;
 37     double k;
 38 }e[500005];
 39 
 40 double f[505][505];
 41 
 42 int g[505][505], c[505];
 43 
 44 inline bool cmp(const edge &a, const edge &b)
 45 {
 46     return a.k > b.k;
 47 }
 48 
 49 signed main(void)
 50 {
 51     n = nextInt();
 52     m = nextInt();
 53     
 54     for (int i = 1; i <= m; ++i)
 55     {
 56         ++c[e[i].x = nextInt()];
 57         ++c[e[i].y = nextInt()];
 58         
 59         ++g[e[i].x][e[i].y];
 60         ++g[e[i].y][e[i].x];
 61     }
 62     
 63     for (int i = 1; i < n; ++i)
 64         for (int j = 1; j < n; ++j)
 65         {
 66             if (i == j)
 67                 f[i][j] = -1.0;
 68             else
 69                 f[i][j] = 1.0 * g[i][j] / c[j];
 70         }
 71     
 72     f[1][n] = -1.0;
 73     
 74     {
 75         for (int i = 1; i < n; ++i)
 76         {
 77             int r = i;
 78             
 79             for (int j = i + 1; j < n; ++j)
 80                 if (fabs(f[j][i]) > fabs(f[r][i]))
 81                     r = j;
 82                     
 83             for (int j = 1; j <= n; ++j)
 84                 std::swap(f[i][j], f[r][j]);
 85             
 86             for (int j = i + 1; j < n; ++j)
 87             {
 88                 long double t = f[j][i] / f[i][i];
 89                 
 90                 for (int k = i; k <= n; ++k)
 91                     f[j][k] -= t * f[i][k];
 92             }
 93         }
 94         
 95         for (int i = n - 1; i >= 0; --i)
 96         {
 97             for (int j = i + 1; j < n; ++j)
 98                 f[i][n] -= f[j][n] * f[i][j];
 99             
100             f[i][n] /= f[i][i];
101         }
102     }
103     
104     for (int i = 1; i <= m; ++i)
105         e[i].k = f[e[i].x][n] / c[e[i].x] + f[e[i].y][n] / c[e[i].y];
106         
107     std::sort(e + 1, e + m + 1, cmp);
108     
109     double ans = 0.0;
110     
111     for (int i = 1; i <= m; ++i)
112         ans += e[i].k * i;
113         
114     printf("%.3lf\n", ans);
115 }

 

@Author: YouSiki

 

posted @ 2017-01-09 16:23  YouSiki  阅读(270)  评论(3编辑  收藏  举报