HDU -- 5001 Walk(2014鞍山网络赛E)(概率)

本文深入解析了一道图论问题的解题思路,重点在于理解如何通过概率和路径计算,求解特定条件下未访问特定节点的概率。通过逐步分析和实例演示,文章详细阐述了每一步背后的逻辑与数学原理,旨在帮助读者掌握此类问题的解决方法。
摘要由CSDN通过智能技术生成

题意:给一个无向图,要在这个图上走d步,每个点被选为起点的概率相同,每个点到和它相邻的点的概率相同。求d步都没走到某个点的概率。

http://acm.hdu.edu.cn/showproblem.php?pid=5001

感觉很简单的样子,但是比赛的时候就是连样例都过不了QAQ。。。

看别人的题解说是每次删掉一的点,走d步到达其他点的概率之和就是d步都不到这个点的概率(ans[i] = ∑p[d][i])。

但是这是为什么呢?

首先,p[i][j]表示第i步走到j的概率,p[i][j] = ∑p[i - 1][v] / e;(v是和j相邻的顶点,e是以v为起点的边数)

一下子想不出来ans[i] = ∑p[d][i]

我们先想只走一步。这样就变成了前1步不走cur的概率 = 第一步走到其他点的概率和。这显然成立。。。

然后我们再想要走两步的情况:前2步不走cur的概率 = 第2步走到其他点的概率和。想到这时已经保证了第1步不走cur,相当于保证了前2步都不走cur!

所以等式成立。

推广到走d步。前d步都不走到cur的情况下走到其他点的概率之和就是ans[cur]!

#include <map>
#include <set>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

typedef double DB;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;

#define pb push_back
#define MP make_pair
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1

const DB eps = 1e-8;
const int inf = 0x3f3f3f3f;
const int mod = 10000007;
const int maxn = 2000 + 10;

int T, n, m, d;
DB p[11111][55], ans[55];
vector<int> V[55];
int main(){
    scanf("%d", &T);
    while(T--){
        scanf("%d%d%d", &n, &m, &d);
        for(int i=1; i<=n; i++) V[i].clear();
        for(int i=1; i<=m; i++){
            int a, b;
            scanf("%d%d", &a, &b);
            V[a].pb(b);
            V[b].pb(a);
        }
        for(int cur=1; cur<=n; cur++){///枚举不走的点
            memset(p, 0, sizeof(p));
            for(int i=1; i<=n; i++) p[0][i] = 1.0 / n;///选每个点做起点的概率都是1/n
            for(int i=1; i<=d; i++){
                for(int j=1; j<=n; j++) if(j != cur){///不从cur走
                    for(unsigned k=0; k<V[j].size(); k++){///枚举所有和j相邻的点
                        int v = V[j][k];
                        p[i][v] += p[i - 1][j] / (DB)V[j].size();///p[i][v]表示第i步到v的概率
                    }
                }
            }
            ans[cur] = 0.0;
            for(int i=1; i<=n; i++) if(i != cur){
                ans[cur] += p[d][i];
            }
        }
        for(int i=1; i<=n; i++) printf("%.10f\n", ans[i]);
    }
    return 0;
}

比赛的时候我们是分别从每个点出发,计算第i步到j的概率,再把每步不到j的概率乘起来,就是每步都不到j的概率。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值