hdu 4305 Lightning 生成树计数

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;
}

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

时间: 2024-10-09 04:09:55

hdu 4305 Lightning 生成树计数的相关文章

HDOJ 4305 Lightning 生成树计数

Lightning Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1588    Accepted Submission(s): 525 Problem Description There are N robots standing on the ground (Don't know why. Don't know how). Sud

HDU 4305 Lightning Matrix Tree定理

题目链接:https://vjudge.net/problem/HDU-4305 解法:首先是根据两点的距离不大于R,而且中间没有点建立一个图.之后就是求生成树计数了. Matrix-Tree定理(Kirchhoff矩阵-树定理).Matrix-Tree定理是解决生成树计数问题最有力的武器之一.它首先于1847年被Kirchhoff证明.在介绍定理之前,我们首先明确几个概念: 1.G的度数矩阵D[G]是一个n*n的矩阵,并且满足:当i≠j时,dij=0:当i=j时,dij等于vi的度数. 2.G

HDU4305:Lightning(生成树计数+判断点是否在线段上)

Lightning Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2465    Accepted Submission(s): 912 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4305 Description: There are N robots standing on the

hdu 4305 生成树奇数问题

Lightning Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1457    Accepted Submission(s): 469 Problem Description There are N robots standing on the ground (Don't know why. Don't know how). Sudd

kuangbin带你飞 生成树专题 : 次小生成树; 最小树形图;生成树计数

第一个部分 前4题 次小生成树 算法:首先如果生成了最小生成树,那么这些树上的所有的边都进行标记.标记为树边. 接下来进行枚举,枚举任意一条不在MST上的边,如果加入这条边,那么肯定会在这棵树上形成一个环,如果还要维护处树的特点 那么就要在这个环上删去一条边,这样他还是树,删掉的边显然是这条链上权值最大边更可能形成次小生成树.那么就有2中方法可以做. 第一种PRIM在prim时候直接可以做出这个从I到J的链上权值最大的值MAX[i][j]; 同时可以用kruskal同样方式标记树边,然后DFS跑

生成树计数

生成树计数就是统计一张图中一共有多少种构造生成树的方案. 大概要用到组合数学等等的数学知识. 以下内容均来自NOI2007国家集训队论文 周冬 <生成树的计数及其应用>: ------------------------- Matrix-Tree定理(Kirchhoff矩阵-树定理).Matrix-Tree定理是解决生成树计数问题最有力的武器之一.它首先于1847年被Kirchhoff证明.在介绍定理之前,我们首先明确几个概念: 1.G的度数矩阵D[G]是一个n*n的矩阵,并且满足:当i≠j时

bzoj1002 生成树计数 找规律

这道题第一眼是生成树计数,n是100,是可以用O(n^3)的求基尔霍夫矩阵的n-1阶的子矩阵的行列式求解的,但是题目中并没有说取模之类的话,就不好办了. 用高精度?有分数出现. 用辗转相除的思想,让它不出现分数.但过程中会出现负数,高精度处理负数太麻烦. 用Python打表?好吧,Python还不熟,写不出来..... 所以,如果这道题我考场上遇到,最多用double骗到n<=20的情况的部分分. 最终只能求助于题解了... 好像是通过观察行列式的特点,推导出关于答案f(n)的递推式(f(n)=

Uva 10766 Organising the Organisation (Matrix_tree 生成树计数)

题目描述: 一个由n个部门组成的公司现在需要分层,但是由于员工间的一些小小矛盾,使得他们并不愿意做上下级,问在满足他们要求以后有多少种分层的方案数? 解题思路: 生成树计数模板题,建立Kirchhoff矩阵,利用Matrix_tree定理求解. Kirchhoff矩阵:假设G为n*n矩阵,C为G的入度矩阵(i==j时,C[i][j]等于i的入度;i!=j时,C[i][j]等于零),A为G的邻接矩阵,那么就有Kirchhoff矩阵等于C-A. Matrix_tree定理:G的不同生成树的个数等于其

SPOJ104 Highways,生成树计数

高速公路(SPOJ104 Highways) 一个有n座城市的组成国家,城市1至n编号,其中一些城市之间可以修建高速公路.现在,需要有选择的修建一些高速公路,从而组成一个交通网络.你的任务是计算有多少种方案,使得任意两座城市之间恰好只有一条路径? 数据规模:1≤n≤12. 生成树计数 算法步骤: 1. 构建拉普拉斯矩阵 Matrix[i][j] = degree(i) , i==j -1,i-j有边 0,其他情况 2. 去掉第r行,第r列(r任意) 3. 计算矩阵的行列式 #include <m