码迷,mamicode.com
首页 > 其他好文 > 详细

hdu 4305 Lightning 生成树计数

时间:2019-10-17 00:48:53      阅读:110      评论:0      收藏:0      [点我收藏+]

标签:顶点   a*   cin   生成树   printf   i+1   eof   邻接   无向图   

Matrix-Tree定理

对于一个n个顶点的无向图G
度矩阵D:设i顶点的度数为du[i],则D[i][i]=du[i]
邻接矩阵A:若i和j之间有边,则A[i][j]=1,否则为0
Kirchhoff矩阵C:C=D-A
Matrix-Tree定理:对于一个无向图G,它的生成树个数等于其Kirchhoff矩阵任何一个n-1阶主子式的行列式的绝对值。

例题

题目链接:hdu 4305
思路:先按要求建图,再求出Kirchhoff矩阵C,最后求C的任何一个n-1阶行列式的绝对值

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 310;
const int mod = 10007;
LL x[N],y[N];
LL dis[N][N];
LL a[N][N];
LL inv(LL a,LL b)
{
    LL res=1;
    while(b)
    {
        if(b&1)res=(res*a)%mod;
        b>>=1;
        a=(a*a)%mod;
    }
    return res;
}
int judge(int i,int j,int k)//判断k是否是i和j连线上的点
{
    LL x1=x[j]-x[i],y1=y[j]-y[i];
    LL x2=x[k]-x[i],y2=y[k]-y[i];
    if(x1*y2==x2*y1&&x1*x2>=0&&dis[i][j]>dis[i][k])return 1;
    return 0;
}
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        memset(a,0,sizeof(a));
        memset(dis,0,sizeof(dis));
        int n;
        LL r;
        scanf("%d%lld",&n,&r);
        for(int i=1;i<=n;i++)
            scanf("%lld%lld",&x[i],&y[i]);
        for(int i=1;i<=n;i++)
            for(int j=i+1;j<=n;j++)
                dis[i][j]=dis[j][i]=(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]);
        for(int i=1;i<=n;i++)
        {
            for(int j=i+1;j<=n;j++)
            {
                if(dis[i][j]>r*r)continue;
                int k;
                for(k=1;k<=n;k++)
                {
                    if(k==i||k==j)continue;
                    if(judge(i,j,k))break;
                }
                if(k>n)
                {
                    a[i][j]=a[j][i]=-1;
                    a[i][i]++;a[j][j]++;
                }
            }
        }
        LL ans=1;
        //化成下三角形
        for(int i=1;i<n;i++)
        {
            LL t=inv(a[i][i],mod-2);
            for(int j=i+1;j<n;j++)
            {
                LL tmp=a[j][i]*t%mod;
                for(int k=1;k<n;k++)
                    a[j][k]=(a[j][k]-a[i][k]*tmp%mod+mod)%mod;
            }
        }
        for(int i=1;i<n;i++)
            ans=ans*a[i][i]%mod;
        if(ans==0)printf("-1\n");
        else printf("%lld\n",ans);
    }
    return 0;
}

hdu 4305 Lightning 生成树计数

标签:顶点   a*   cin   生成树   printf   i+1   eof   邻接   无向图   

原文地址:https://www.cnblogs.com/HooYing/p/11689473.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!