HDU 5001 Walk


用邻接矩阵维护从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;
}


你可能感兴趣的:(HDU 5001 Walk)