[BZOJ5297][Cqoi2018]社交网络(Matrix-Tree 矩阵-树定理)

Address

https://www.lydsy.com/JudgeOnline/problem.php?id=5297

Solution

矩阵树定理的拓展——外向树生成树计数。
基尔霍夫矩阵 C C 入度矩阵减去邻接矩阵。
辅助矩阵两个: B(n×m) D(m×n) D ( m × n )
对于第 i i 条有向边 <u,v> B[u,i]=1,B[v,i]=D[i,v]1 B [ u , i ] = 1 , B [ v , i ] = D [ i , v ] − 1 B B D 其他位置为 0 0
同样 BD 等于基尔霍夫矩阵。
利用 Binet-Cauthy 定理将 矩阵乘积的行列式展开,就得到:

|C1,1|=|S|=n1|C1,1(S)| | C 1 , 1 | = ∑ | S | = n − 1 | C 1 , 1 ( S ) |

C(S) C ( S ) 为边集 S S 构成的基尔霍夫矩阵。
易得 |C1,1(S)| 表示选出的 n1 n − 1 条边是否构成外向树,构成外向树则为 1 1 ,否则为 0
题目要求取模,用逆元处理即可。
丢个链接:
https://blog.csdn.net/xyz32768/article/details/81413569

Code

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define For(i, a, b) for (i = a; i <= b; i++)
using namespace std;
inline int read() {
    int res = 0; bool bo = 0; char c;
    while (((c = getchar()) < '0' || c > '9') && c != '-');
    if (c == '-') bo = 1; else res = c - 48;
    while ((c = getchar()) >= '0' && c <= '9')
        res = (res << 3) + (res << 1) + (c - 48);
    return bo ? ~res + 1 : res;
}
const int N = 255, PYZ = 10007;
int n, m, a[N][N], inv[PYZ];
int gauss() {
    int i, j, k, ans = 1, ok = 0; For (i, 2, n) {
        int id = -1; For (j, i, n) if (a[j][i]) {id = j; break;}
        if (id == -1) return 0; if (id != i) {
            For (j, 2, n) swap(a[i][j], a[id][j]); ok ^= 1;
        }
        For (j, i + 1, n) {
            int kd = 1ll * inv[a[i][i]] * a[j][i] % PYZ;
            For (k, 2, n) a[j][k] =
                (a[j][k] - 1ll * a[i][k] * kd % PYZ + PYZ) % PYZ;
        }
        ans = 1ll * ans * a[i][i] % PYZ;
    }
    return ok ? (PYZ - ans) % PYZ : ans;
}
int main() {
    int i, j, x, y; n = read(); m = read();
    while (m--) y = read(), x = read(), a[x][y] = (a[x][y] + PYZ - 1) % PYZ,
    a[y][y]++; inv[1] = 1; For (i, 2, PYZ - 1)
        inv[i] = 1ll * (PYZ - PYZ / i) * inv[PYZ % i] % PYZ;
    cout << gauss() << endl; return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值