PowerOJ1180-矩阵快速幂

来源:互联网 发布:决策树算法例题 编辑:程序博客网 时间:2024/06/07 12:53

题目链接


 1180: 寻找大黄 SPJ

Time Limit: 11000 MS Memory Limit: 2097152 KB
Total Submit: 26 Accepted: 5 Page View: 32
Submit Status Discuss

    总所周知,大黄经常到处跑出去玩。对,没错,就是今天!院赛啊!大黄,又双叒叕跑出去耍了,把院赛的事情都搞忘了。无奈,我们只能让小梁晨去找她了。梁晨预判,大黄现在肯定在绵阳市范围内。我们可以把绵阳市看做一个由nn个点mm条边组成的无向图,且我们西科大对应的点的编号为11。每一分钟,大黄会等概率地走到和她当前所在点相邻的点。现在距离大黄离开西科大已经kk分钟了。梁晨想知道,现在大黄停留在每一个点的概率。

输入第一行有两个正整数n,m,kn,m,k2n2002≤n≤2001mn×(n1)21≤m≤n×(n−1)20k1050≤k≤105)。分别代表绵阳市的点数,双向边的条数,和大黄离开西科大的时间。 接下来mm行,每行两个正整数ui,viui,vi,表示点uiui和点vivi存在一条双向边。保证给出的图没有重边和自环。
输出n个数,表示现在大黄停留在每一个点的概率。 要求绝对误差或者相对误差小于10610−6
3 3 31 22 31 3
0.25 0.375 0.375

题目大意:


给你一张无向图,初始在节点1 接下来k分钟你将等概率的移动到其他相连接的节点,每条边花费1分钟,

问k分钟后经过每个节点的概率是多少


题目思路:


刚看到这题时想的是bfs来做,,但是发现如果暴力的话可能会超内存,因为k太大了,,然后就像其他方法

记得之前做过一道类似的求u->v经过k条边的最短路,其实这一类都是属于邻接矩阵乘法的应用,所以就考虑

矩阵快速幂来解决,对于G[i][j]^k表示i->j经过k分钟的概率,所以我们就考虑如何构造矩阵,对于G[i][j]^1 我们

可以从题目给出的图来构造,首先记录下所有的边和点的度,所以对于边ij G[i][j] = 1.0/in[i]  in[i]表示i的度

然后 ans = ans*G 因为初始时在1  所以ans[0][0] = 1  然后就是用快速幂来求


AC代码:


#include<bits/stdc++.h>using namespace std; struct Matrix{    double M[205][205];};Matrix M,ans; int in[205];int n,m,k;struct st{    int x,y;}s[40000]; Matrix cal(Matrix a,Matrix b,int x){    Matrix c;    for(int i=0;i<x;i++)    {        for(int j=0;j<n;j++)        {            double sum = 0;            for(int k=0;k<n;k++)            {                sum+=a.M[i][k]*b.M[k][j];            }            c.M[i][j] = sum;        }    }    return c;} void sove(){    while(k)    {        if(k&1)        {            ans = cal(ans,M,1);        }        M =cal(M,M,n);        k/=2;    }} int main(){    cin>>n>>m>>k;    memset(M.M,0,sizeof(M));    memset(in,0,sizeof(in));    for(int i=0;i<m;i++)    {        int x,y;scanf("%d%d",&x,&y);        x--,y--;        in[x]++,in[y]++;        s[i].x = x,s[i].y = y;    }    for(int i=0;i<m;i++)    {        int x = s[i].x,y = s[i].y;        M.M[x][y] = (double)1.00/in[x];        M.M[y][x] = (double)1.00/in[y];    }    memset(ans.M,0,sizeof(ans.M));    ans.M[0][0] = 1.0;    sove();    for(int i=0;i<n;i++)    {        printf("%lf%c",ans.M[0][i],i==n-1?'\n':' ');    }     return 0;}

  






1 0
原创粉丝点击