我们定义图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;
}