当前位置: 代码迷 >> 综合 >> HDU 4305 Lightning (生成图计数+判断点在线段上)
  详细解决方案

HDU 4305 Lightning (生成图计数+判断点在线段上)

热度:92   发布时间:2024-02-07 03:43:11.0

题意:根据两点的距离不大于R,而且中间没有点建立一个图。求生成树计数。

题解:生成图计数+判断点在线段上
oi-wiki索引:Kirchhoff 矩阵树定理

在这里插入图片描述
则无向图G的生成树个数 = Kirchhoff 矩阵L 的 n-1 阶主子式的行列式的绝对值。

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<fstream>
#include<set>
#include<map>
#include<sstream>
#include<iomanip>
#define ll long long
using namespace std;
const int MOD = 10007;
int INV[MOD];
const double eps = 1e-8;
const double inf = 1e20;
const double pi = acos(-1.0);
const int maxp = 1010;
//Compares a double to zero
int sgn(double x) {if (fabs(x) < eps) return 0;if (x < 0) return -1;else return 1;
}
//square of a double
inline double sqr(double x) { return x * x; }//POINT
struct Point {double x, y;Point() {}Point(double _x, double _y) {x = _x;y = _y;}Point operator -(const Point& b)const {return Point(x - b.x, y - b.y);}//叉积double operator ^(const Point& b)const {return x * b.y - y * b.x;}//点积double operator *(const Point& b)const {return x * b.x + y * b.y;}Point operator *(const double& k)const {return Point(x * k, y * k);}
};//LINE
struct Line {Point s, e;Line() {}Line(Point _s, Point _e) {s = _s;e = _e;}// 点在线段上的判断bool pointonseg(Point p) {return sgn((p - s) ^ (e - s)) == 0 && sgn((p - s) * (p - e)) <= 0;}
};//求ax = 1( mod m) 的x值,就是逆元(0<a<m)
long long inv(long long a, long long m) {if (a == 1)return 1;return inv(m % a, m) * (m - m / a) % m;
}
struct Matrix {int mat[330][330];void init() {memset(mat, 0, sizeof(mat));}int det(int n) {    //求行列式的值模上MOD,需要使用逆元for (int i = 0; i < n; i++)for (int j = 0; j < n; j++)mat[i][j] = (mat[i][j] % MOD + MOD) % MOD;int res = 1;for (int i = 0; i < n; i++) {for (int j = i; j < n; j++)if (mat[j][i] != 0) {for (int k = i; k < n; k++)swap(mat[i][k], mat[j][k]);if (i != j)res = (-res + MOD) % MOD;break;}if (mat[i][i] == 0) {res = -1;//不存在(也就是行列式值为0)break;}for (int j = i + 1; j < n; j++) {//int mut = (mat[j][i]*INV[mat[i][i]])%MOD;//打表逆元int mut = (mat[j][i] * inv(mat[i][i], MOD)) % MOD;for (int k = i; k < n; k++)mat[j][k] = (mat[j][k] - (mat[i][k] * mut) % MOD + MOD) % MOD;}res = (res * mat[i][i]) % MOD;}return res;}
};
int ccw(int x1, int y1, int x2, int y2, int x3, int y3) {int v = (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1);if (v == 0) return 0;return 1;
}
int t, n, r, x[333], y[333], g[333][333];
int ck(int i, int j) {if ((x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]) > r * r) return 0;for (int k = 0; k < n; k++) {if (k == i || k == j) continue;Line l = Line(Point(x[i], y[i]), Point(x[j], y[j]));if (l.pointonseg(Point(x[k], y[k]))) return 0;}return 1;
}
int main() {for (int i = 1; i < MOD; i++) INV[i] = inv(i, MOD);scanf("%d", &t);while (t--) {memset(g, 0, sizeof(g));scanf("%d%d", &n, &r);for (int i = 0; i < n; i++) scanf("%d%d", &x[i], &y[i]);for (int i = 0; i < n; i++) {for (int j = i + 1; j < n; j++) {if (!ck(i, j)) continue;g[i][j] = g[j][i] = 1;}}Matrix ma;ma.init();for (int i = 0; i < n; i++)for (int j = 0; j < n; j++)if (i != j && g[i][j]) {ma.mat[i][j] = -1;ma.mat[i][i]++;}printf("%d\n", ma.det(n - 1));}return 0;
}