Lightning

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1099    Accepted Submission(s): 363

Problem Description
There are N robots standing on the ground (Don't know why. Don't know how). 

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. 

 
Input
There are several cases.
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. 
 
Output
One line for each case contains the answer.
 
Sample Input
3
3 2
-1 0
0 1
1 0
3 2
-1 0
0 0
1 0
3 1
-1 0
0 1
1 0
 
Sample Output
3
1
-1
 
Author
BUPT
 
Source
 
Recommend
zhuyuanchen520
 

首先是根据两点的距离不大于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(计算几何,判断点在线段上,生成树计数)的更多相关文章

  1. HDU - 4305 - Lightning 生成树计数 + 叉积判断三点共线

    HDU - 4305 题意: 比较裸的一道生成树计数问题,构造Krichhoof矩阵,求解行列式即可.但是这道题还有一个限制,就是给定的坐标中,两点连线中不能有其他的点,否则这两点就不能连接.枚举点, ...

  2. hdu 1086(计算几何入门题——计算线段交点个数)

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=1086 You can Solve a Geometry Problem too Time Limit: 2 ...

  3. POJ-2318 TOYS 计算几何 判断点在线段的位置

    题目链接:https://cn.vjudge.net/problem/POJ-2318 题意 在一个矩形内,给出n-1条线段,把矩形分成n快四边形 问某些点在那个四边形内 思路 二分+判断点与位置关系 ...

  4. HDU 4305 Lightning Matrix Tree定理

    题目链接:https://vjudge.net/problem/HDU-4305 解法:首先是根据两点的距离不大于R,而且中间没有点建立一个图.之后就是求生成树计数了. Matrix-Tree定理(K ...

  5. POJ 1584 A Round Peg in a Ground Hole 判断凸多边形 点到线段距离 点在多边形内

    首先判断是不是凸多边形 然后判断圆是否在凸多边形内 不知道给出的点是顺时针还是逆时针,所以用判断是否在多边形内的模板,不用是否在凸多边形内的模板 POJ 1584 A Round Peg in a G ...

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

    Lightning Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total S ...

  7. poj 1127 -- Jack Straws(计算几何判断两线段相交 + 并查集)

    Jack Straws In the game of Jack Straws, a number of plastic or wooden "straws" are dumped ...

  8. hdu 4643 GSM 计算几何 - 点线关系

    /* hdu 4643 GSM 计算几何 - 点线关系 N个城市,任意两个城市之间都有沿他们之间直线的铁路 M个基站 问从城市A到城市B需要切换几次基站 当从基站a切换到基站b时,切换的地点就是ab的 ...

  9. hdu acm 1166 敌兵布阵 (线段树)

    敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submi ...

随机推荐

  1. JQuery实现AJAX实例

    <script type="text/javascript" src="ReportServer?op=emb&resource=finereport.js ...

  2. JavaScript中创建对象的5种模式

    构造函数模式 实现方式: function Person(name, age, job) { this.name = name; this.age = age; this.job = job; thi ...

  3. Elasticsearch源码分析(一)启动流程 ModuleBuilder injector

    http://blog.csdn.net/u010994304/article/details/50452890 es启动脚本是bin目录下的elasticsearch. 脚本内容不再赘述,java主 ...

  4. conso.log占位符

    %d占位符表示number %s占位符表示string %f占位符表示浮点数 %o占位符表示对象 

  5. python标准库之【socket】

    socket通常也称作”套接字“.网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket.socket 是网络连接端点.例如当你的Web浏览器请求www.fishc. ...

  6. 《java并发编程实战》读书笔记5--任务执行, Executor框架

    第6章 任务执行 6.1 在线程中执行任务 第一步要找出清晰的任务边界.大多数服务器应用程序都提供了一种自然的任务边界选择方式:以独立的请求为边界. -6.6.1 串行地执行任务 最简单的任务调度策略 ...

  7. 八:Zookeeper开源客户端Curator的api测试

    curator是Netflix公司开源的一套ZooKeeper客户端,Curator解决了很多ZooKeeper客户端非常底层的细节开发工作.包括连接重连,反复注册Watcher等.实现了Fluent ...

  8. 【javascript】基于javascript的小时钟

    计时事件:通过JavaScript,我们可以设置在一段时间间隔后执行一段代码,而不仅仅是在函数调用后立即执行. 在JavaScript中,使用计时事件是很容易的,主要有两个事件供我们使用 setTim ...

  9. mongoDB学习第一天之增删改查

    mongoDB 是 no-sql 的一种数据库. 创建数据库: use dbName #数据库中如果存在 dbName ,切换到此数据库:如果不存在此数据库,则创建 dbName 数据库!(tip:当 ...

  10. 88. Merge Sorted Array【Easy】【双指针-不用额外空间归并两个有序数组】

    Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array. Note: T ...