zoukankan      html  css  js  c++  java
  • 【BZOJ】1875: [SDOI2009]HH去散步 矩阵快速幂

    【题意】给定n个点m边的无向图,求A到B恰好经过t条边的路径数,路径须满足每条边都和前一条边不同。n<=20,m<=60,t<=2^30。

    【算法】矩阵快速幂

    【题解】将图的邻接矩阵进行矩阵快速幂就可以得到恰好经过t条边的路径数,但不能满足题目要求。

    改为对原图的边进行相互连边,将经过同一个点的边两两连边,这样就是新邻接矩阵的t-1步。

    为了满足题目要求,当两条边互为反向边时不连边即可。

    最后乘上从A出发的边的矩阵,然后统计到达B的路径数。

    复杂度O((m*2)^3 log t)。

    #include<cstdio>
    #include<cstring>
    const int maxn=130,MOD=45989;
    int n,m,t,A,B,a[maxn][maxn],ans[maxn][maxn],c[maxn][maxn],tot=1,first[maxn];
    struct edge{int v,from;}e[maxn];
     
    void multply(int a[maxn][maxn],int b[maxn][maxn]){
        for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)c[i][j]=0;
        for(int i=1;i<=n;i++)
            for(int k=1;k<=n;k++)
                for(int j=1;j<=n;j++)c[i][j]=(c[i][j]+a[i][k]*b[k][j])%MOD;
        for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)a[i][j]=c[i][j];
    }
    void insert(int u,int v){tot++;e[tot].v=v;e[tot].from=first[u];first[u]=tot;}
    int main(){
        scanf("%d%d%d%d%d",&n,&m,&t,&A,&B);A++;B++;
        for(int i=1;i<=m;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            insert(++u,++v);insert(v,u);
        }
        for(int i=2;i<=tot;i++){
            for(int j=first[e[i].v];j;j=e[j].from)if(i!=(j^1)){
                a[i][j]++;
            }
        }
        for(int i=first[A];i;i=e[i].from)a[1][i]++;//
        n=tot;
        for(int i=1;i<=n;i++)ans[i][i]=1;
        while(t){
            if(t&1)multply(ans,a);
            multply(a,a);
            t>>=1;
        }
        int ANS=0;
        for(int i=first[B];i;i=e[i].from)ANS=(ANS+ans[1][i^1])%MOD;
        printf("%d",ANS);
        return 0;
    }
    View Code
  • 相关阅读:
    线程池、进程池(concurrent.futures模块)和协程
    python中socket、进程、线程、协程、池的创建方式和应用场景
    IO多路复用和local概念
    pymysql模块
    HTML初识
    CSS之选择器
    CSS之样式属性(背景固定、圆形头像、模态框)
    字符串格式的方法%s、format和python3.6新特性f-string和类型注解
    common-pool2 使用
    apache-common pool的使用
  • 原文地址:https://www.cnblogs.com/onioncyc/p/8486898.html
Copyright © 2011-2022 走看看