zoukankan      html  css  js  c++  java
  • 题解 P4111 [HEOI2015]小 Z 的房间

    题解

    题目大意:给定一个无向图,求它的生成树个数。

    一道裸的矩阵树定理,外加一些建图的技巧。

    矩阵树定理

    对于一个 (Laplace) 矩阵,其去掉任意一行后的行列式即为答案。

    行列式不会的看这里

    (Laplace) 矩阵是一个无向图的邻接矩阵转化而来的,其中 (L_{i,i}) 代表 (i) 的度数,(L_{i,j}) 代表 (i->j) 有多少条路径(准确的说是这些路径的权值和,求生成树时设为 (1) )。

    至于怎么算,看这里

    那么有了这些知识,我们就可以 (A) 了这题。

    注意,这题中模数不是质数,不能求逆元,所以我们消元时要用辗转相除法,所以真正的时间复杂度为 (mathcal O((nm)^3log_{nm}))

    Code

    (AC kern 0.5emCODE:)

    #include<bits/stdc++.h>
    #define ri register signed
    #define p(i) ++i
    using namespace std;
    namespace IO{
        char buf[1<<21],*p1=buf,*p2=buf;
        #define gc() p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++
        inline int read() {
            ri x=0,f=1;char ch=getchar();
            while(ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
            while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
            return x*f; 
        }
    }
    using IO::read;
    namespace nanfeng{
        #define int long long
        #define cmax(x,y) ((x)>(y)?(x):(y))
        #define cmin(x,y) ((x)>(y)?(y):(x))
        #define FI FILE *IN
        #define FO FILE *OUT
        static const int MOD=1e9,N=15;
        int id[N][N],G[N*N][N*N],deg[N*N],n,m,cnt,ans=1;
        char h[N][N];
        inline void add(int u,int v) {G[u][v]=G[v][u]=1;}
        inline int main() {
            // FI=freopen("nanfeng.in","r",stdin);
            // FO=freopen("nanfeng.out","w",stdout);
            n=read(),m=read();
            for (ri i(1);i<=n;p(i)) {
                scanf("%s",h[i]+1);
                for (ri j(1);j<=m;p(j)) if (h[i][j]=='.') id[i][j]=p(cnt); 
            }
            for (ri i(1);i<=n;p(i)) {
                for (ri j(1);j<=m;p(j)) {
                    if (id[i][j]&&id[i][j-1]) add(id[i][j],id[i][j-1]);
                    if (id[i][j]&&id[i-1][j]) add(id[i][j],id[i-1][j]);
                }
            }
            for (ri i(1);i<=cnt;p(i)) {
                for (ri j(1);j<=cnt;p(j)) if (G[i][j]) p(deg[i]);
            }
            for (ri i(1);i<=cnt;p(i)) {
                for (ri j(1);j<=cnt;p(j)) {
                    if (i==j) G[i][j]=deg[i];
                    else G[i][j]=-G[i][j];
                }   
            }
            cnt-=1;
            for (ri i(1);i<=cnt;p(i)) {//这是高斯消元,要化成三角矩阵,而不要以高斯约旦法消成对角线矩阵。
                for (ri j(i+1);j<=cnt;p(j)) {
                    while(G[j][i]) {
                        int k=G[i][i]/G[j][i];
                        for (ri l(i);l<=cnt;p(l)) G[i][l]=(G[i][l]-G[j][l]*k%MOD+MOD)%MOD;
                        swap(G[i],G[j]);
                        ans*=-1;
                    }
                }
                ans=(ans*G[i][i]%MOD+MOD)%MOD;
            } //求行列式
            printf("%lld
    ",(ans+MOD)%MOD);
            return 0;
        }
        #undef int
    }
    int main() {return nanfeng::main();}
    
  • 相关阅读:
    js 生成指定范围之内的随机数
    vue项目在ie浏览器打开做提示
    vue 瀑布流组件
    docker 移动文件到其他目录
    学习hyperf遇到的问题
    Linux 部署elasticsearch
    Git 常用命令
    Linux svn定时更新
    eclipse 导入web项目后,线程假死
    向量基本概念
  • 原文地址:https://www.cnblogs.com/nanfeng-blog/p/14880913.html
Copyright © 2011-2022 走看看