标签:return int double HNOI2013 次数 Maxn 游走 include
问题分析
发现边经过的次数实际上就是点经过的次数乘上概率。那么问题就变成了求每个点经过的次数。
把无向边拆成两条有向边,然后把点 \(n\) 的所有出边都删掉。然后高斯消元即可。每个点经过的次数就是可以走到它的点的次数乘上概率之和。当然点 \(1\) 要额外加 \(1\) ,因为一开始是在点 \(1\) 。
参考程序
#include <cstdio>
#include <algorithm>
#include <cmath>
#define Maxn 510
#define Eps 1e-12
int n, m, Map[Maxn][Maxn], Sz[Maxn], Id[Maxn * Maxn];
double A[Maxn][Maxn], Times[Maxn * Maxn];
inline int Cmp(double x, double y) {
if (fabs(x - y) < Eps) return 0;
if (x - y > Eps) return -1; else return 1;
}
inline void Gauss() {
for (int i = 1; i <= n; ++i) {
for (int j = i; j <= n; ++j)
if (Cmp(A[i][j], 0) != 0) {
for (int k = 1; k <= n + 1; ++k)
std::swap(A[i][k], A[j][k]);
break;
}
double Tmp = A[i][i];
for (int j = 1; j <= n + 1; ++j) A[i][j] /= Tmp;
for (int j = 1; j <= n; ++j) {
if (i == j) continue;
Tmp = A[j][i];
for (int k = 1; k <= n + 1; ++k)
A[j][k] -= Tmp * A[i][k];
}
}
return;
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1, x, y; i <= m; ++i) {
scanf("%d%d", &x, &y);
++Sz[x]; Map[x][y] = i;
++Sz[y]; Map[y][x] = i;
}
for (int i = 1; i <= n; ++i)
for (int j = 1; j < n; ++j)
if (Map[j][i])
A[i][j] = -1.0 / Sz[j];
for (int i = 1; i <= n; ++i) A[i][i] = 1;
A[1][n + 1] = 1;
Gauss();
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j)
Times[Map[i][j]] = ((i != n) ? A[i][n + 1] / Sz[i] : 0) + ((j != n) ? A[j][n + 1] / Sz[j] : 0);
for (int i = 1; i <= m; ++i) Id[i] = i;
std::sort(Id + 1, Id + m + 1, [](int x, int y)->bool{ return Cmp(Times[x], Times[y]) == -1;});
double Ans = 0;
for (int i = 1; i <= m; ++i) Ans += Times[Id[i]] * i;
printf("%.3lf\n", Ans);
return 0;
}
标签:return,int,double,HNOI2013,次数,Maxn,游走,include 来源: https://www.cnblogs.com/chy-2003/p/12046151.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。