题意:给你一个无向图,你从任意一个起点出发,每到一个节点,随机去往与该节点相邻的一个节点,问你走了d步之后,不经 过每一个点的概率是多少。
思路:枚举目标点,用dp[i][j]表示第i步第一次到达第j个点的概率。注意 是第一次。
然后再用 1-∑dp[i][pos] pos为目标点。重点是,对于每一步下的循环,如果第j个点为目标点就跳过它,
否则第i+1步到达第k个点的概率就加上第i步到达第j个点的概率再除以第j个点的度数。还有,注意dp数组的初始化。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <string> #include <map> #include <queue> #include <vector> using namespace std; typedef long long ll; const int MAXN=55; const int MAXD=11000; vector<int> G[MAXN]; double dp[MAXD][MAXN]; int main() { //freopen("in.txt","r",stdin); int n,m,d,u,v,T; scanf("%d",&T); while(T--) { scanf("%d%d%d",&n,&m,&d); for(int i=0;i<=n;i++) G[i].clear(); while(m--) { scanf("%d%d",&u,&v); G[u].push_back(v); G[v].push_back(u); } for(int dis=1;dis<=n;dis++) { double ans=0; memset(dp,0,sizeof(dp)); for(int i=1;i<=n;i++) dp[0][i]=1.0/n; for(int i=0;i<d;i++) { for(int j=1;j<=n;j++) { if(j==dis) continue; else { for(int k=0;k<G[j].size();k++) dp[i+1][G[j][k]]+=dp[i][j]/G[j].size(); } } } for(int i=0;i<=d;i++) ans+=dp[i][dis]; printf("%.10f\n",1-ans); } } return 0; }