当前位置: 首页 > 工具软件 > lightning4j > 使用案例 >

Lightning(生成树计数)

仲孙鸿畴
2023-12-01

原题: http://acm.hdu.edu.cn/showproblem.php?pid=4305

题意:

n个点,任意两个点之间可以连边当且仅当距离不大于R,并且中间没有其他边。求生成树个数。

解析:

判断中间有没有点可以直接n3for,也可以n2log,枚举每个点为起点,其他的点与之形成的向量用map比较是否存在即可。

连完边就用矩阵树进行n3做就行了。

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define ll long long

const ll p = 10007;

const int maxn=309;
int x[maxn],y[maxn];

bool f[maxn][maxn];
ll c[maxn][maxn];
ll det(ll n) {
    ll ret=1;
    for(int i=0; i<n; i++) {
        for(int j=i+1; j<n; j++)
            while(c[j][i]) {
                ll t=c[i][i]/c[j][i];
                for(int k=i; k<n; k++)
                    c[i][k]=(c[i][k]-c[j][k]*t)%p;
                swap(c[i],c[j]);
                ret=-ret;
            }
        if(c[i][i]==0)
            return 0;
        ret=ret*c[i][i]%p;
    }
    return (ret+p)%p;
}
inline void link(int a,int b) {
    f[a][b]=1;
    f[b][a]=1;
}
int fa[maxn];
int fin(int i){return fa[i]==i?i:fa[i]=fin(fa[i]); }
void deal(int n) {
    rep(i,1,n)fa[i]=i;
    memset(c,0,sizeof c);
    int sum=n;
    rep(i,1,n){
        rep(j,i+1,n){
            if(f[i][j]){
                int f1=fin(i),f2=fin(j);
                if(f1!=f2){
                    sum--;
                    fa[f1]=f2;
                }
                c[i-1][j-1]--;
                c[i-1][i-1]++;
                c[j-1][i-1]--;
                c[j-1][j-1]++;
            }
        }
    }
    if(sum>1){
        printf("-1\n");
        return ;
    }
    printf("%lld\n",det(n-1));
}

struct pair_hash
{
    template<class T1, class T2>
    std::size_t operator() (const std::pair<T1, T2>& p) const
    {
        auto h1 = std::hash<T1>{}(p.first);
        auto h2 = std::hash<T2>{}(p.second);
        return h1 ^ h2;
    }
};

int main() {
    int t;
    scanf("%d",&t);
    while(t--) {
        memset(f,0,sizeof f);
        int n,r;
        scanf("%d%d",&n,&r);
        rep(i,1,n) {
            scanf("%d%d",x+i,y+i);
        }
        rep(i,1,n) {
            unordered_map<pair<int,int>,int,pair_hash>M;
            rep(j,1,n) {
                if(i==j)
                    continue;
                int X=x[j]-x[i],Y=y[j]-y[i];
                double L=sqrt(1.0*X*X+1.0*Y*Y);
                if(L>(double)r)
                    continue;
                int gcd=__gcd(X,Y);
                X/=gcd,Y/=gcd;
                if(M.count({X,Y})==0) {
                    M[ {X,Y}]=j;
                } else {
                    int p0=M[ {X,Y}];
                    double L0=sqrt(1.0*(x[p0]-x[i])*(x[p0]-x[i])+1.0*(y[p0]-y[i])*(y[p0]-y[i]));
                    if(L<L0) {
                        M[ {X,Y}]=j;
                    }
                }
            }
            for(auto p:M) {
                link(i,p.second);
            }
        }
        deal(n);
    }
}

 类似资料: