swust oj 2620

题目链接:https://www.oj.swust.edu.cn/problem/show/2620
题目大意:给一个n个点m条边的图,保证数据无重边,无自环。顶点编号1到n,一个人从1出发,每一分钟,会等概率地走到和她当前所在点相邻的点。问你经过k分钟后,这个人在各个点的概率
数据范围:2<=n<=200 、1<=m<=(n-1)*n/2、k<=10^5
题目分析:可以把这个人从i点到另外n个点(包括自己)的概率列出来,可以构造一个n*n的矩阵。因为这个人从1出发的,所以初始矩阵是定了的[1,0,0,0,…,0],代表在第一分钟里,他在1号节点的概率是1,其他地方是0,然后矩阵乘法即可。这里由于k很大,所以需要用二分幂矩阵。
这个题比较有意思,如果学习过机器学习的知识的话,应该能反应过来这个题是一个比较明显马尔科夫矩阵问题。

代码:

#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#include<iostream>

using namespace std;

vector<int>grid[205];
double markov[205][205];

void init_markov_matrix(int n)
{
    int i,j;
    for(i=0;i<=n;++i)
    {
        grid[i].clear();
        for(j=0;j<=n;++j)
            markov[i][j]=0;
    }
}

//矩阵乘法
void muilt_martix(double P[][205],double Q[][205],int n)
{
    int i,j,k;
    double X[205][205];
    for(i=1;i<=n;++i)
        for(j=1;j<=n;++j)
        {
            X[i][j]=0;
            for(k=1;k<=n;++k)
                X[i][j]+=P[i][k]*Q[k][j];
        }
    for(i=1;i<=n;++i)
        for(j=1;j<=n;++j)
            P[i][j]=X[i][j];
}

//矩阵乘方快速算法
void markov_power(int n,int k,double P[][205])
{
    double Q[205][205];
    int i,j;
    for(i=1;i<=n;++i)
        for(j=1;j<=n;++j)
        {
            Q[i][j]=markov[i][j];
            if(i==j)
                P[i][j]=1;
            else
                P[i][j]=0;
        }
    if(k==0)
        return;
    while(k!=1)
    {
        if(k&1)
        {
            --k;
            muilt_martix(P,Q,n);
        }
        else
        {
            k=k>>1;
            muilt_martix(Q,Q,n);
        }
    }
    muilt_martix(P,Q,n);
}

int main()
{
    int n,m,k,i,j,u,v;
    while(scanf("%d%d%d",&n,&m,&k)!=EOF)
    {
        init_markov_matrix(n);
        for(i=0;i<m;++i)
        {
            scanf("%d%d",&u,&v);
            grid[u].push_back(v);
            grid[v].push_back(u);
        }
        vector<int>::iterator iter;
        double M[205],S[205];
        for(i=1;i<=n;++i)
        {
            if(i==1)
                M[i]=1;
            else
                M[i]=0;
            double rate=1.0/double(grid[i].size());
            for(iter=grid[i].begin();iter!=grid[i].end();++iter)
                markov[i][*iter]=rate;
            markov[i][i]=0.0;
        }
        double P[205][205];
        //马尔科夫矩阵自乘K次,再乘以[1,0,0,0,0...,0]即答案(取第一行)
        markov_power(n,k,P);
        for(i=1;i<n;++i)
            printf("%lf ",P[1][i]);
        printf("%lf\n",P[1][n]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/xieshimao/article/details/73188424