题意:
连通无向图 随机选起点 随机乱走 可以重复走点 问 每个点有多大几率不被路过
思路:
一看就是DP题…
但是开始的时候陷入了僵局 我是想先算路过每个点的概率然后用1减去这个概率 但是由于可以重复路过 所以无法判断是不是第一次经过这个点
所以我们应该直接做不路过的概率 即类似bfs的一步步走 如果走到了要计算的点就停下来 意思就是除了要计算概率的那个点不能走以外 其他都能走 最后统计下概率的和就是不路过这个点的概率
PS:
这题一定要用邻接表 我一开始看这图可能是完全图而且n只有50 就用了邻接矩阵 然后就T了 换邻接表就1218MS
代码:
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<map>
#include<set>
#include<vector>
#include<cassert>
using namespace std;
typedef long long LL;
#define Q 401
#define N 51
#define M 10001
#define inf 2147483647
#define mod 1000000007
#define lowbit(x) (x&(-x))
int t, n, m, p, tot;
int head[N], d[N];
double dp[M][N];
struct edge {
int v, next;
} ed[N * N * 2];
void add(int u, int v) {
ed[tot].v = v;
ed[tot].next = head[u];
head[u] = tot++;
}
int main() {
int i, j, k, f;
double ans;
scanf("%d", &t);
while (t--) {
scanf("%d%d%d", &n, &m, &p);
for (i = 1; i <= n; i++) {
head[i] = -1;
d[i] = 0;
}
tot = 0;
for (i = 1; i <= m; i++) {
scanf("%d%d", &j, &k);
d[j]++;
d[k]++;
add(j, k);
add(k, j);
}
for (i = 1; i <= n; i++) {
for (j = 1; j <= n; j++) {
if (i != j)
dp[0][j] = 1.0 / n;
else
dp[0][j] = 0;
}
for (f = 1; f <= p; f++) {
for (j = 1; j <= n; j++)
dp[f][j] = 0;
for (j = 1; j <= n; j++) {
if (i == j)
continue;
for (k = head[j]; ~k; k = ed[k].next)
dp[f][ed[k].v] += dp[f - 1][j] / d[j];
}
}
ans = 0;
for (j = 1; j <= n; j++) {
if (i != j)
ans += dp[p][j];
}
printf("%f\n", ans);
}
}
return 0;
}