zoukankan      html  css  js  c++  java
  • 生成树计数问题(SPOJ 104 Highways)

      周冬的《生成树的计数及其应用》论文上讲到过生成树计数的问题。

    用到的是一个Kirchhoff矩阵,它是这样定义的:

    a、设一个度数矩阵D,当i == j时,Dij = (i这个节点的度数),否则Dij = 0;

    b、设一个连通性矩阵A,如果i 和j连通,则Aij等于i到j的边数,否则Aij等于0;

    Kirchhoff矩阵C = D - A;

    有了Kirchhoff矩阵这个工具,我们可以引入Matrix-Tree定理:
    对于一个无向图G,它的生成树个数等于其Kirchhoff矩阵任何一个n-1阶主子式的行列式的绝对值(可以用高斯消元解,线性代数没学好的面壁去。。。-_-!)。
    所谓n-1阶主子式,就是对于任意一个r,将C的第r行和第r列同时删去后的新矩阵,用Cr表示。

    代码(SPOJ 104 Highways)

    View Code
    //#pragma comment(linker,"/STACK:327680000,327680000")
    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <vector>
    #include <cstring>
    #include <algorithm>
    #include <string>
    #include <set>
    #include <functional>
    #include <numeric>
    #include <sstream>
    #include <stack>
    #include <map>
    #include <queue>
    
    #define CL(arr, val) memset(arr, val, sizeof(arr))
    #define REP(i, n)for((i) = 0; (i) < (n); ++(i))
    #define FOR(i, l, h)for((i) = (l); (i) <= (h); ++(i))
    #define FORD(i, h, l)for((i) = (h); (i) >= (l); --(i))
    #define L(x)(x) << 1
    #define R(x)(x) << 1 | 1
    #define MID(l, r)(l + r) >> 1
    #define Min(x, y)x < y ? x : y
    #define Max(x, y)x < y ? y : x
    #define E(x)(1 << (x))
    #define iabs(x) (x) < 0 ? -(x) : (x)
    #define OUT(x)printf("%I64d\n", x)
    #define lowbit(x)(x)&(-x)
    #define Read()freopen("data.in", "r", stdin)
    #define Write()freopen("data.out", "w", stdout);
    
    const double eps = 1e-8;
    typedef long long LL;
    const int inf = ~0u>>2;
    
    using namespace std;
    
    const int N = 111;
    const int M = 2111;
    const int MOD = 31011;
    
    int b[N];
    
    bool zero(double x) {
        return x > -eps && x < eps;
    }
    
    double det(double mat[N][N], int n) {
        double mul, res = 1;
        int i, j, k;
        for(i = 0; i < n; ++i)  b[i] = i;
        for(i = 0; i < n; ++i) {
            if(zero(mat[b[i]][i])) {
                for(j = i + 1; j < n; ++j) {
                    if(!zero(mat[b[j]][i])) {swap(b[i], b[j]); res *= -1; break;}
                }
            }
            res *= mat[b[i]][i];
            for(j = i + 1; j < n; ++j) {
                if(!zero(mat[b[j]][i])) {
                    mul = mat[b[j]][i]/mat[b[i]][i];
                    for(k = i; k < n; ++k) {
                        mat[b[j]][k] -= mat[b[i]][k]*mul;
                    }
                }
            }
        }
        return res;
    }
    
    
    int D[N][N], A[N][N];
    double G[N][N];
    
    int main() {
        //freopen("data.in", "r", stdin);
    
        int T, i, j;
        int n, m, x, y;
        cin >> T;
        while(T--) {
            scanf("%d%d", &n, &m);
            CL(D, 0);
            CL(A, 0);
            while(m--) {
                scanf("%d%d", &x, &y);
                A[x-1][y-1] = A[y-1][x-1] = 1;
            }
            for(i = 0; i < n; ++i) {
                x = 0;
                for(j = 0; j < n; ++j) {
                    if(A[i][j])    {x++;}
                }
                D[i][i] = x;
            }
            for(i = 0; i < n; ++i) {
                for(j = 0; j < n; ++j)  G[i][j] = D[i][j] - A[i][j];
            }
            printf("%.0f\n", det(G, n-1));
        }
        return 0;
    }
  • 相关阅读:
    【ThreadX】Azure RTOS ThreadX概述
    -- spi flash 擦除接口调用HAL库不同函数的区别
    STM32 芯片锁死解决方法
    【KEIL】User's Guide
    【KEIL】Software Packs
    【KEIL 】Options for File
    使用CubeMX创建TouchGFX工程时LCD死活不显示
    【转】获取本地图片的URL
    printf 函数格式控制
    【集成】touchgfx 之 《Using C code with TouchGFX》
  • 原文地址:https://www.cnblogs.com/vongang/p/2712839.html
Copyright © 2011-2022 走看看