HDU--4305(生成树计数)

2015-09-07 22:23:26

传送门

题意:平面上300个点,如果两点之间距离<=R,且两点形成的线段上没有另外的点,那么两点之间有一条无向边。问生成树的方案数。

思路:暴力n^2建图,关于判断两点形成线段上是否有其他点,比如判断 k 点知否在 i ,j 之间,首先看斜率是否相等,不能直接求斜率,而应该转化为乘式;再判断 dis(i,k)+dis(k,j)是否等于 dis(i,j),如果斜率一样且距离相等那么 k 点在 i,j 之间。

  建完图后就是Matrix-Tree定理的运用了,注意取模。

 

#include <cstdio>
#include <ctime>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;

#define getmid(l,r) ((l) + ((r) - (l)) / 2)
#define MP(a,b) make_pair(a,b)
#define PB push_back

typedef long long ll;
typedef pair<int,int> pii;
const double eps = 1e-8;
const int INF = (1 << 30) - 1;
const int MAXN = 310;
const int mod = 10007;

int T;
int N,R;
int X[MAXN],Y[MAXN];
double dis[MAXN][MAXN];
int G[MAXN][MAXN];
int vis[MAXN];

int sign(double x){
    if(fabs(x) < eps) return 0;
    if(x < 0) return -1;
    return 1;
}

double Dis(int a,int b){
    return sqrt(1.0 * (X[a] - X[b]) * (X[a] - X[b]) + 
            1.0 * (Y[a] - Y[b]) * (Y[a] - Y[b]));
}

void Dfs(int p){
    vis[p] = 1;
    for(int i = 1; i <= N; ++i) if(G[p][i] && !vis[i]) Dfs(i);
}

int Det(int n){
    int A[MAXN][MAXN];
    for(int i = 1; i <= n; ++i)
        for(int j = 1; j <= n; ++j)
            A[i][j] = G[i][j];
    int res = 1;
    for(int i = 1; i <= n; ++i){
        for(int j = i + 1; j <= n; ++j){
            while(A[j][i]){
                int t = A[i][i] / A[j][i];
                for(int k = i; k <= n; ++k)
                    A[i][k] = (A[i][k] - A[j][k] * t) % mod;
                for(int k = i; k <= n; ++k)
                    swap(A[i][k],A[j][k]);
                res = -res; //行列式换行,值取反
            }
        }
        if(!A[i][i]) return 0;
        res = res * A[i][i] % mod;
    }
    return (res + mod) % mod;
}

int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&N,&R);
        for(int i = 1; i <= N; ++i){
        scanf("%d%d",X + i,Y + i);
            for(int j = 1; j < i; ++j){
                dis[i][j] = dis[j][i] = Dis(i,j);
            }
        }
        memset(G,0,sizeof(G));
        for(int i = 1; i <= N; ++i){
            for(int j = i + 1; j <= N; ++j) if(!(dis[i][j] > R)){
                bool can = true;
                for(int k = 1; k <= N; ++k) if(k != i && k != j){
                    if((Y[j] - Y[i]) * (X[k] - X[i]) ==
                        (Y[k] - Y[i]) * (X[j] - X[i]) && 
                        sign(dis[i][k] + dis[k][j] - dis[i][j]) == 0){
                        can = false;
                        break;
                    }
                }
                if(can){
                    G[i][i]++;
                    G[j][j]++;
                    G[i][j] = G[j][i] = -1;
                }
            }
        }
        memset(vis,0,sizeof(vis));
        Dfs(1);
        bool flag = true;
        for(int i = 1; i <= N; ++i) if(!vis[i]) flag = false;
        if(!flag){
            printf("-1\n");
            continue;
        }
        int ans = Det(N - 1);
        printf("%d\n",ans);
    }
    return 0;
}

 

 

  

posted @ 2015-09-07 22:35  Naturain  阅读(166)  评论(0编辑  收藏  举报