生成树计数

@(XSY)[行列式, Matrix-Tree定理]
之前写过一个辗转相除版本的, 这里来一个求逆元的.

#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>

const int N = 80, MOD = (int)1e9 + 7;
int n, m;
int det[N + 1][N + 1];

namespace Zeonfai
{
	inline int getInt()
	{
		int sgn = 1, a = 0;
		char c;

		while(! isdigit(c = getchar()))
			if(c == '-')
				sgn *= -1;

		while(isdigit(c))
			a = a * 10 + c - '0', c = getchar();

		return a * sgn;
	}
}

inline int modPower(int a, int x)
{
	int res = 1;
	
	for(; x; a = (long long)a * a % MOD, x >>= 1)
		if(x & 1)
			res = (long long)res * a % MOD;
	
	return res;
}

inline int gause()
{
	for(int i = 1; i < n; ++ i)
		for(int j = 1; j < n; ++ j)
			det[i][j] = (det[i][j] + MOD) % MOD;
	
	int sgn = 1;

	for(int i = 1; i < n; ++ i)
	{
		int p = i;

		for(; p < n; ++ p)
			if(det[p][i])
				break;

		if(p >= n)
			continue;

		if(p ^ i)
		{
			sgn *= -1;

			for(int j = 1; j < n; ++ j)
				std::swap(det[i][j], det[p][j]);
		}
		
		int inv = modPower(det[i][i], MOD - 2);

		for(int j = i + 1; j < n; ++ j)
			if(det[i][j])
			{
				int tmp = (long long)det[j][i] * inv % MOD;
				
				for(int k = i; k < n; ++ k)
					det[j][k] = (det[j][k] - (long long)det[i][k] * tmp % MOD + MOD) % MOD;
			}
	}
	
	int ans = 1;

	for(int i = 1; i < n; ++ i)
		ans = (long long)ans * det[i][i] % MOD;
	
	if(sgn == -1)
		ans = (MOD - ans) % MOD;

	return ans;
}
/*
inline int gause()
{
    for(int i = 1; i < n; i ++)
        for(int j = 1; j < n; j ++)
            det[i][j] = (det[i][j] + MOD) % MOD;
            
    long long sgn = 0;
    
    for(int i = 1; i < n; i ++)
    {
        int j;
        
        for(j = i; j < n; j ++)
            if(det[j][i])
                break;
        
        if(j == n)
            continue;
        
        if(i != j)
        {
            sgn ^= i ^ j;
            
            for(int k = i; k < n; k ++)
                std::swap(det[j][k], det[i][k]);
        }
        
        for(int j = i + 1; j < n; j ++)
            while(det[j][i])
            {
                int tmp = det[j][i] / det[i][i];
                
                for(int k = i; k < n; k ++)
                    det[j][k] = (det[j][k] - (long long)det[i][k] * tmp % MOD + MOD) % MOD;
                    
                if(! det[j][i])
                    break;
                    
                sgn ^= 1;
                
                for(int k = i; k < n; k ++)
                    std::swap(det[i][k], det[j][k]);
            }
    }
    
    long long ret = 1;
    
    for(int i = 1; i < n; i ++)
        ret = (ret * det[i][i]) % MOD;
        
    if(sgn)
        ret = (MOD - ret) % MOD;
        
    return ret;
}*/

int main()
{
	#ifndef ONLINE_JUDGE
	freopen("treecount.in", "r", stdin);
	freopen("treecount.out", "w", stdout);
	#endif

	using namespace Zeonfai;
	n = getInt(), m = getInt();
	memset(det, 0, sizeof(det));

	for(int i = 0; i < m; ++ i)
	{
		int u = getInt(), v = getInt();
		-- det[u][v], ++ det[u][u], -- det[v][u], ++ det[v][v];
	}

	printf("%d\n", gause());
}
posted @ 2017-04-17 09:07  Zeonfai  阅读(173)  评论(0编辑  收藏  举报