HDU 4305 Lightning(计算几何,判断点在线段上,生成树计数)
Lightning
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1099 Accepted Submission(s): 363

Suddenly the sky turns into gray, and lightning storm comes! Unfortunately, one of the robots is stuck by the lightning!

So it becomes overladen. Once a robot becomes overladen, it will spread lightning to the near one.
The spreading happens when:
Robot A is overladen but robot B not.
The Distance between robot A and robot B is no longer than R.
No other robots stand in a line between them.
In this condition, robot B becomes overladen.
We assume that no two spreading happens at a same time and no two robots stand at a same position.

The problem is: How many kind of lightning shape if all robots is overladen? The answer can be very large so we output the answer modulo 10007. If some of the robots cannot be overladen, just output -1.
The first line is an integer T (T < = 20), indicate the test cases.
For each case, the first line contains integer N ( 1 < = N < = 300 ) and R ( 0 < = R < = 20000 ), indicate there stand N robots; following N lines, each contains two integers ( x, y ) ( -10000 < = x, y < = 10000 ), indicate the position of the robot.
3 2
-1 0
0 1
1 0
3 2
-1 0
0 0
1 0
3 1
-1 0
0 1
1 0
1
-1
首先是根据两点的距离不大于R,而且中间没有点建立一个图。
之后就是求生成树计数了。
Matrix-Tree定理(Kirchhoff矩阵-树定理)。Matrix-Tree定理是解决生成树计数问题最有力的武器之一。它首先于1847年被Kirchhoff证明。在介绍定理之前,我们首先明确几个概念:
1、G的度数矩阵D[G]是一个n*n的矩阵,并且满足:当i≠j时,dij=0;当i=j时,dij等于vi的度数。
2、G的邻接矩阵A[G]也是一个n*n的矩阵, 并且满足:如果vi、vj之间有边直接相连,则aij=1,否则为0。
我们定义G的Kirchhoff矩阵(也称为拉普拉斯算子)C[G]为C[G]=D[G]-A[G],则Matrix-Tree定理可以描述为:G的所有不同的生成树的个数等于其Kirchhoff矩阵C[G]任何一个n-1阶主子式的行列式的绝对值。所谓n-1阶主子式,就是对于r(1≤r≤n),将C[G]的第r行、第r列同时去掉后得到的新矩阵,用Cr[G]表示。
#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <string.h>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <list>
#include <string>
#include <math.h>
using namespace std; struct Point
{
int x,y;
Point(int _x = ,int _y = )
{
x = _x,y = _y;
}
Point operator - (const Point &b)const
{
return Point(x-b.x,y-b.y);
}
int operator ^(const Point &b)const
{
return x*b.y - y*b.x;
}
void input()
{
scanf("%d%d",&x,&y);
}
};
struct Line
{
Point s,e;
Line(){}
Line(Point _s,Point _e)
{
s = _s;
e = _e;
}
};
bool onSeg(Point P,Line L)
{
return
((L.s-P)^(L.e-P)) == &&
(P.x-L.s.x)*(P.x-L.e.x) <= &&
(P.y-L.s.y)*(P.y-L.e.y) <= ;
}
int sqdis(Point a,Point b)
{
return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
} const int MOD = ;
int INV[MOD];
//求ax = 1( mod m) 的x值,就是逆元(0<a<m)
long long inv(long long a,long long m)
{
if(a == )return ;
return inv(m%a,m)*(m-m/a)%m;
}
struct Matrix
{
int mat[][];
void init()
{
memset(mat,,sizeof(mat));
}
int det(int n)//求行列式的值模上MOD,需要使用逆元
{
for(int i = ;i < n;i++)
for(int j = ;j < n;j++)
mat[i][j] = (mat[i][j]%MOD+MOD)%MOD;
int res = ;
for(int i = ;i < n;i++)
{
for(int j = i;j < n;j++)
if(mat[j][i]!=)
{
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] == )
{
res = -;//不存在(也就是行列式值为0)
break;
}
for(int j = i+;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;
}
}; Point p[];
int n,R;
bool check(int k1,int k2)//判断两点的距离小于等于R,而且中间没有点阻隔
{
if(sqdis(p[k1],p[k2]) > R*R)return false;
for(int i = ;i < n;i++)
if(i!=k1 && i!=k2)
if(onSeg(p[i],Line(p[k1],p[k2])))
return false;
return true;
}
int g[][];
int main()
{
//预处理逆元
for(int i = ;i < MOD;i++)
INV[i] = inv(i,MOD);
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&R);
for(int i = ;i < n;i++)
p[i].input();
memset(g,,sizeof(g));
for(int i = ;i < n;i++)
for(int j = i+;j <n;j++)
if(check(i,j))
g[i][j] = g[j][i] = ;
Matrix ret;
ret.init();
for(int i = ;i < n;i++)
for(int j = ;j < n;j++)
if(i != j && g[i][j])
{
ret.mat[i][j] = -;
ret.mat[i][i]++;
}
printf("%d\n",ret.det(n-));
}
return ;
}
HDU 4305 Lightning(计算几何,判断点在线段上,生成树计数)的更多相关文章
- HDU - 4305 - Lightning 生成树计数 + 叉积判断三点共线
HDU - 4305 题意: 比较裸的一道生成树计数问题,构造Krichhoof矩阵,求解行列式即可.但是这道题还有一个限制,就是给定的坐标中,两点连线中不能有其他的点,否则这两点就不能连接.枚举点, ...
- hdu 1086(计算几何入门题——计算线段交点个数)
链接:http://acm.hdu.edu.cn/showproblem.php?pid=1086 You can Solve a Geometry Problem too Time Limit: 2 ...
- POJ-2318 TOYS 计算几何 判断点在线段的位置
题目链接:https://cn.vjudge.net/problem/POJ-2318 题意 在一个矩形内,给出n-1条线段,把矩形分成n快四边形 问某些点在那个四边形内 思路 二分+判断点与位置关系 ...
- HDU 4305 Lightning Matrix Tree定理
题目链接:https://vjudge.net/problem/HDU-4305 解法:首先是根据两点的距离不大于R,而且中间没有点建立一个图.之后就是求生成树计数了. Matrix-Tree定理(K ...
- POJ 1584 A Round Peg in a Ground Hole 判断凸多边形 点到线段距离 点在多边形内
首先判断是不是凸多边形 然后判断圆是否在凸多边形内 不知道给出的点是顺时针还是逆时针,所以用判断是否在多边形内的模板,不用是否在凸多边形内的模板 POJ 1584 A Round Peg in a G ...
- HDU4305:Lightning(生成树计数+判断点是否在线段上)
Lightning Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total S ...
- poj 1127 -- Jack Straws(计算几何判断两线段相交 + 并查集)
Jack Straws In the game of Jack Straws, a number of plastic or wooden "straws" are dumped ...
- hdu 4643 GSM 计算几何 - 点线关系
/* hdu 4643 GSM 计算几何 - 点线关系 N个城市,任意两个城市之间都有沿他们之间直线的铁路 M个基站 问从城市A到城市B需要切换几次基站 当从基站a切换到基站b时,切换的地点就是ab的 ...
- hdu acm 1166 敌兵布阵 (线段树)
敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submi ...
随机推荐
- 爬虫===登陆CSDN的方法
本文主要介绍csdn的登陆,可应用在爬虫上~ # -*- coding:utf-8 -*- import json import requestsfrom xlutils.copy import co ...
- XCopy复制文件夹命令及参数详解以及xcopy拷贝目录并排除特定文件
XCOPY是COPY的扩展,可以把指定的目录连文件和目录结构一并拷贝,但不能拷贝系统文件:使用时源盘符.源目标路径名.源文件名至少指定一个:选用/S时对源目录下及其子目录下的所有文件进行COPY.除非 ...
- Linux配置Tomcat
系统:Ubuntu,Tomcat:apache-tomcat-8.5.23.tar.gz 1,找到apache-tomcat-8.5.23.tar.gz,复制到 /usr/local root@ubu ...
- C++ Primer读书笔记
以前阅读学习C++ Primer时的习题代码(当时代码风格格式比较渣): https://github.com/liyuan989/exercise/tree/master/c%2B%2B%20pri ...
- Redis 集群使用(2)
Redis包含三种集群策略: 主从复制 哨兵模式 redis cluster 主从复制 在主从复制中,数据分为两类:主数据库(master)和 从数据库(slave).其中主从复制有如下特点: 主数据 ...
- [ 总结 ] Linux系统启动流程
Linux系统启动过程分析: 按下电源 --> BIOS自检 --> 系统引导(lilo/grub) --> 启动内核 --> 初始化系统 --> 用户登录 1. BIO ...
- 数据库SQL实战(1)
1.查找最晚入职员工的所有信息: CREATE TABLE `employees` ( `emp_no` int(11) NOT NULL, `birth_date` date NOT NULL, ` ...
- php上传文件常见错误
今天在文件上传过程中遇到的文件上传不过去,和网页报错,最后经查看总结有以下几个方面 上传文件错误码 error=0 正常上传 error=1 上传的大小超过了input[type=file]的文件上传 ...
- 树莓派使用opencv
安装 reference1 reference2 注意 安装顺利,但是使用的时候提示 you need install libgtk2.0-dev xxx ,这时候说明你安装的库的顺序不对,你应该先安 ...
- webpy 上传文件
x = web.input(myfile={})是一个类字典对象,会返回所有GET或POST的数据 括号内部用来设置myfile的默认值,以防请求中根本就没有myfile键 定义如下一个表单 form ...