[模板] 矩阵树定理

简介

矩阵树定理 - OI Wiki

矩阵树定理可以求无/有向图生成树个数.

对于无向图:
定义度数矩阵 \(D\), 邻接矩阵 \(E\), 那么基尔霍夫矩阵 \(K = D - E\).

图的生成树个数 \(t(G) = \det(K_{ii})\), 其中 \(K_{ii}\) 表示\(K\) 去掉第 \(i\) 行和第 \(i\) 列的余子式.

不会证...

矩阵树定理也适用于有向图:

根向树形图 \(\leftrightarrow K_{out}\);

叶向树形图 \(\leftrightarrow K_{in}\).

总之不是根就是啦...

推论

  1. \(n\) 个点有标号完全图生成树个数为 \(n^{n-2}\).
  2. 一个完全二分图, 两部分点数分别为 \(n_1\), \(n_2\), 它的生成树个数为 $n_1^{n_2 - 1} n_2^{n_1 - 1} $.

利用 prüfer 序列可以得到相同的结果.

另外, 使用 prüfer 序列还可以得到如下结果:

  1. \(n\) 个点, 每个点 \(i\) 度数为 \(d_i\), 树的个数为
    \[ \binom {n-2}{d_1-1,d_2-1,\dotsc, d_n-1}\]

代码

//main part

//undirected
void adde(int f,int t){
    ++a[f][f],++a[t][t],--a[f][t],--a[t][f];
}

ll matt(){
    return det(n-1);
}

//directed, to leaf
void adde(int f,int t){
    ++a[t][t],--a[f][t];
}

//to root
void adde(int f,int t){
    ++a[f][f],--a[f][t];
}

ll matt(int rt){
    rep(i,1,n)if(i!=rt&&i!=n)swap(a[rt][i],a[n][i]),swap(a[i][rt],a[i][n]);
    swap(a[rt][rt],a[n][n]);
    return det(n-1);
}
//matrix
il ll getv(ll a){return a<0?a+nmod:a;}
il void exgcd(ll a,ll b,ll &x,ll &y,ll &d){//a&b should >= 0
    b?(exgcd(b,a%b,y,x,d),y-=a/b*x):(x=1,y=0,d=x);
}
il ll inv(ll v){
    ll x,y,d;
    exgcd(getv(v),nmod,x,y,d);
    return getv(x%nmod);
}


ll a[nsz][nsz];
ll det(int n){
    ll ans=1;
    ll v,tmp;
    rep(i,1,n){
        int p0=i;
        rep(j,i+1,n)if(abs(a[p0][i])<abs(a[j][i]))p0=j;
        if(a[p0][i]==0)return 0;
        if(p0!=i){ans=-ans;rep(j,1,n)swap(a[i][j],a[p0][j]);}
        v=inv(a[i][i]),ans=ans*a[i][i]%nmod;
        rep(j,1,n){
            if(j==i)continue;
            tmp=v*a[j][i]%nmod;
            rep(k,i,n)a[j][k]=(a[j][k]-tmp*a[i][k])%nmod;//possibly -
        }
    }
    return getv(ans%nmod);
}


void adde(int f,int t){
    ++a[f][f],++a[t][t],--a[f][t],--a[t][f];
}

ll matt(){
    return det(n-1);
}

转载于:https://www.cnblogs.com/ubospica/p/10439662.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值