hdu4305生成树计数Matrix-tree

我们定义图G的基尔霍夫矩阵C[G]=D[G]-A[G]. 

即度数矩阵减邻接矩阵

度数矩阵:


基尔霍夫矩阵的性质: 
①对于任意一个图,他的基尔霍夫矩阵C的行列式的值为0. 
因为显然基尔霍夫矩阵的每一行或者列上元素的和都是0啊= = 
②如果图G不连通,其基尔霍夫矩阵的任意主子式行列式值为0.

③若图G是一棵树,则C[G]的任意一个n-1阶主子式的行列式的值为1. 

G 的所有不同的生成树的个数等于其基尔霍夫矩阵C[G]任何一个 n-1 阶主子式的行列式的绝对值。 

O(n^3)

#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
const int maxn=300;
const int N=310;
const int mod=1e4+7;
ll x[maxn+10],y[maxn+10];
ll G[maxn+10][maxn+10];
ll dis(int a,int b);
ll exgcd(ll a,ll b,ll &x,ll &y);
ll Gauss(ll C[][N],int n);
int main()
{
    int t,n;
    ll r;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%lld",&n,&r);
        for(int i=0; i<n; i++) scanf("%lld%lld",&x[i],&y[i]);
        for(int i=0; i<n; i++)
            for(int j=0; j<n; j++) G[i][j]=0;
        for(int i=0; i<n; i++)
            for(int j=i+1; j<n; j++)
            {
                if(dis(i,j)<=r*r)
                {
                    bool flag=true;
                    for(int k=0; k<n; k++)
                    {
                        if(k==i||k==j)
                            continue;
                        if((x[k]-x[i])*(y[j]-y[k])==(x[j]-x[k])*(y[k]-y[i])&&dis(i,k)<=dis(i,j)&&dis(k,j)<=dis(i,j))
                        {
                            flag=false;
                            break;
                        }
                    }
                    if(flag)
                        G[i][j]=G[j][i]=mod-1;   //直接得到减去邻接矩阵的答案
                }
            }
        for(int i=0; i<n; i++)
            for(int j=i+1; j<n; j++)
                if(G[i][j]==mod-1)
                {
                    G[i][i]++;
                    G[j][j]++;
                }
        ll ans=Gauss(G,n-1);
        if(ans==0) ans--;
        printf("%lld\n",ans);
    }
    return 0;
}
ll dis(int a,int b)
{
    return (x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b]);
}
ll exgcd(ll a,ll b,ll &x,ll &y)//乘法逆元返回的d是a,b的公约数,x是a mod b的逆元
{
    if(b==0)
    {
        x=1ll;
        y=0;
        return a;
    }
    ll d=exgcd(b,a%b,x,y);
    ll t=x;
    x=y;
    y=t-a/b*y;
    return d;
}
ll Gauss(ll C[][N],int n)
{
    ll ans=1;
    int flag=1;
    int i,j,k;
    for(i=0; i<n; i++)
    {
        if(C[i][i]==0)
        {
            for(j=i+1; j<n; j++)
                if(C[j][i])break;
            if(j==n)return 0;
            flag=!flag;
            for(int k=i; k<n; k++)
                swap(C[i][k],C[j][k]);
        }
        ans=ans*C[i][i]%mod;
        ll x,y;
        int tp=exgcd(C[i][i],mod,x,y);
        for(k=i+1; k<n; k++)
            C[i][k]=C[i][k]*x%mod;
        for(int j=i+1; j<n; j++)
            for(int k=i+1; k<n; k++)
            {
                C[j][k]=(C[j][k]-(ll)C[j][i]*C[i][k])%mod;
                if(j==k)
                    C[j][k]=(C[j][k]+mod)%mod;
            }
        for(k=i+1; k<n; k++)
            C[i][k]=(ll)C[i][k]*C[i][i]%mod;

    }
    ans=(ans%mod+mod)%mod;
    if(flag) return ans;
    else  return mod-ans;
}

猜你喜欢

转载自blog.csdn.net/hyacinthhome/article/details/80444938