HDU 5001 Walk

来源:互联网 发布:js正则表达式判断邮箱 编辑:程序博客网 时间:2024/04/28 05:15


用邻接矩阵维护从i 到 j 的概率

因为某些点不能经过,所以将改行该列全部赋值为 0 

用矩阵快速幂

时间复杂度为 O( n^4 log d  )


#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>using namespace std;int a[55][55];int deg[55];double mat[55][55];struct Matrix{    double mat[55][55];    int n, m;    void init(int n, int m){        this->n = n;        this->m = m;        memset(mat, 0, sizeof(mat));    }    Matrix operator * (const Matrix& B){        Matrix C;        C.init(n, B.m);        for(int i=0; i<n; i++){            for(int j=0; j<B.m; j++){                for(int k=0; k<m; k++){                    C.mat[i][j] += mat[i][k] * B.mat[k][j];                }            }        }        return C;    }    Matrix quick_pow(int x){        Matrix Base, ret;        Base.init(n,m);        ret.init(n,m);        for(int i=0; i<n; i++){            for(int j=0; j<m; j++){                Base.mat[i][j]=mat[i][j];                if(i==j) ret.mat[i][j]=1;            }        }        while(x){            if(x&1) ret=ret*Base;            Base=Base*Base;            x>>=1;        }        return ret;    }    void print(){        for(int i=0; i<n; i++){            for(int j=0; j<m; j++){                cout<<mat[i][j]<<" ";            } cout<<endl;        }    }};double b[55];Matrix s;int main(){    int t, n, m, d, x, y;    scanf("%d",&t);    while(t--){        scanf("%d%d%d",&n,&m,&d);        memset(a,0,sizeof a);        memset(deg,0,sizeof deg);        memset(mat,0,sizeof mat);        for(int i=0; i<m; i++){            scanf("%d%d",&x,&y);            x--, y--;            a[x][y]=a[y][x]=1;            deg[x]++, deg[y]++;        }        for(int c=0; c<n; c++){            double sum=0;            for(int i=0; i<n; i++){                for(int j=0; j<n; j++){                    if(a[i][j]) mat[i][j]=1.0/(double)deg[j];                }            }            for(int i=0; i<n; i++){                mat[c][i]=mat[i][c]=0.0;            }            s.init(n,n);            for(int j=0; j<n; j++){                for(int k=0; k<n; k++){                    s.mat[j][k]=mat[j][k];                }            }            s=s.quick_pow(d);            for(int i=0; i<n; i++){                if(i==c) continue;                for(int j=0; j<n; j++){                    if(j==i) b[j]=1.0/(double)n;                    else b[j]=0.0;                }                for(int j=0; j<n; j++){                    for(int k=0; k<n; k++){                        sum+=b[j]*s.mat[k][j];                    }                    //puts("");                }            }            printf("%.10f\n",sum);        }    }    return 0;}


0 0
原创粉丝点击