#### 洛谷传送门
BZOJ传送门
题目描述
奶牛们建立了一个随机化的臭气炸弹来驱逐猪猡。猪猡的文明包含 到 ( )一共 个猪城。这些城市由 ( )条由两个不同端点 和 ( ; )表示的双向道路连接。保证城市 至少连接一个其它的城市。一开始臭气弹会被放在城市 。每个小时(包括第一个小时),它有 ( ; )的概率污染它所在的城市。如果这个小时内它没有污染它所在的城市,那麽它随机地选择一条道路,在这个小时内沿着这条道路走到一个新的城市。可以离开这个城市的所有道路被选择的概率均等。因为这个臭气弹的随机的性质,奶牛们很困惑哪个城市最有可能被污染。给定一个猪猡文明的地图和臭气弹在每个小时内爆炸的概率。计算每个城市最终被污染的概率。如下例,假设这个猪猡文明有两个连接在一起的城市。臭气炸弹从城市1出发,每到一个城市,它都有 的概率爆炸。
可知下面这些路径是炸弹可能经过的路径(最后一个城市是臭气弹爆炸的城市):
: 1
: 1-2
: 1-2-1
: 1-2-1-2
: 1-2-1-2-1
… 要得到炸弹在城市
终止的概率,我们可以把上面的第
,第
,第
……条路径的概率加起来,(也就是上表奇数编号的路径)。上表中第k条路径的概率正好是
,也就是必须在前
个回合离开所在城市(每次的概率为
)并且留在最后一个城市(概率为
)。所以在城市
结束的概率可以表示为
。当我们无限地计算把这些项一个个加起来,我们最后会恰好得到
,也就是我们要求的概率,大约是
。这意味着最终停留在城市
的概率为
,大约为
。
输入输出格式
输入格式
第一行四个正整数
。
以下
行, 每行两个正整数
, 表示编号为
的城市和
的城市之间有一条边。
输出格式
一共 行, 每行一个保留 位的小数,第 行的数表示炸弹在第 个城市爆炸的概率。
输入输出样例
输入样例#1
2 1 1 2
1 2
输出样例#1
0.666666667
0.333333333
解题分析
推一波式子: 设
为点
的度数, 那么大概递推式是这样的:
然后发现这样搞会有环, 那么就高斯消元搞搞就好了。 因为一开始在 号点,所以一号点的值预先设为 。
代码如下:
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <algorithm>
#include <vector>
#define R register
#define IN inline
#define W while
#define MX 305
#define gc getchar()
#define db double
template <class T>
IN void in(T &x)
{
x = 0; R char c = gc;
for (; !isdigit(c); c = gc);
for (; isdigit(c); c = gc)
x = (x << 1) + (x << 3) + c - 48;
}
std::vector <int> to[MX];
int deg[MX];
db mat[MX][MX], pos;
int dot, line, p, q, bd;
void Gauss()
{
R int i, j, k;
for (i = 1; i <= dot; ++i)
{
for (j = i + 1; j <= dot; ++j)
if(fabs(mat[j][i]) > fabs(mat[i][i])) std::swap(mat[j], mat[i]);
for (j = i + 1; j <= bd; ++j) mat[i][j] /= mat[i][i];
for (j = 1; j <= dot; ++j)
{
if(j ^ i)
{
for (k = i + 1; k <= bd; ++k)
mat[j][k] -= mat[j][i] * mat[i][k];
}
}
}
}
int main(void)
{
int a, b;
in(dot), in(line), in(p), in(q); bd = dot + 1;
pos = 1.0 * p / (1.0 * q);
for (R int i = 1; i <= line; ++i)
in(a), in(b), to[a].push_back(b), to[b].push_back(a), ++deg[a], ++deg[b];
mat[1][bd] = 1;
for (R int i = 1; i <= dot; ++i)
{
mat[i][i] = 1;
for (R int j = 0; j < deg[i]; ++j)
mat[i][to[i][j]] = (pos - 1.0) / deg[to[i][j]];
}
Gauss();
for (R int i = 1; i <= dot; ++i) printf("%.9lf\n", mat[i][bd] * pos);
}