HDU5001 Walk

来源:互联网 发布:mac磁盘恢复到单一分区 编辑:程序博客网 时间:2024/06/05 15:59

E - Walk
时限:15000MS     内存:65536KB     64位IO格式:%I64d & %I64u
提交 状态 练习 HDU 5001

问题描述

I used to think I could be anything, but now I know that I couldn't do anything. So I started traveling. 

The nation looks like a connected bidirectional graph, and I am randomly walking on it. It means when I am at node i, I will travel to an adjacent node with the same probability in the next step. I will pick up the start node randomly (each node in the graph has the same probability.), and travel for d steps, noting that I may go through some nodes multiple times. 

If I miss some sights at a node, it will make me unhappy. So I wonder for each node, what is the probability that my path doesn't contain it.
 

输入

The first line contains an integer T, denoting the number of the test cases. 

For each test case, the first line contains 3 integers n, m and d, denoting the number of vertices, the number of edges and the number of steps respectively. Then m lines follows, each containing two integers a and b, denoting there is an edge between node a and node b. 

T<=20, n<=50, n-1<=m<=n*(n-1)/2, 1<=d<=10000. There is no self-loops or multiple edges in the graph, and the graph is connected. The nodes are indexed from 1.
 

输出

For each test cases, output n lines, the i-th line containing the desired probability for the i-th node. 

Your answer will be accepted if its absolute error doesn't exceed 1e-5.
 

样例输入

25 10 1001 22 33 44 51 52 43 52 51 41 310 10 101 22 33 44 55 66 77 88 99 104 9
 

样例输出

0.00000000000.00000000000.00000000000.00000000000.00000000000.69933179670.58642849520.44408608210.22758969910.42940745910.48510487420.48960188420.45250442500.34065674830.6421630037


题目大意:一个人到处乱走,从一个点到他连通的每个相邻点是等概率的。起始点也是等概率的。问最后所有点没有走到过的概率

思路:dp[i][j]其中i表示走的步数,j表示走到的位置的编号,dp表示的是走到这个点的概率。转移方程:dp[i+1][g[j][k]]+=dp[i][j]*p,(用邻接表储存图)第i+1步走到从起始点到k点(j,k连通)的概率等于从起始点第i步到j点的概率乘上j到k的概率p,其中p=1/g[j].size()(因为用邻接表表示所以g[j].size()表示与j点连通的边的个数)。

由于起始点也是随机的,所以我们在图外面再加一个点作为起始点,这个点到所有点都有一条有方向的边,这样就可以解决起始点随机的问题。再然后就把dp[i+1][x]的概率加起来,也就是能到x点的概率的和,最后1减去就是答案。。。

代码:

<span style="color:#cccccc;"> #include <bits/stdc++.h>using namespace std;const int MAX_N=55;const int MAX_M=10005;double dp[MAX_M][MAX_N];vector <int> g[MAX_N];int n,m,d,v,u;double solve(int x){    double ans=0;    memset(dp,0,sizeof(dp));    dp[0][0]=1;    for(int i=0;i<=d;i++)    {        for(int j=0;j<=n;j++)        {            if(x==j) continue;            double p=1.0/(g[j].size());            for(int k=0;k<g[j].size();k++)            {                dp[i+1][g[j][k]]+=dp[i][j]*p;            }        }        ans+=dp[i+1][x];    }    return ans;}int main(){    int 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",&v,&u);            g[v].push_back(u);            g[u].push_back(v);        }        for(int i=1;i<=n;i++)            g[0].push_back(i);        for(int i=1;i<=n;i++)            printf("%.10lf\n",1.0-solve(i));    }    return 0;}</span><span style="color:#008000;"></span>


0 0
原创粉丝点击