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. linux 设备树【转】

    转自:http://blog.csdn.net/chenqianleo/article/details/77779439 [-] linux 设备树 为什么要使用设备树Device Tree 设备树的 ...

  2. monkey测试===Android测试工具Monkey用法简介(转载)

    Monkey是Android中的一个命令行工具,可以运行在模拟器里或实际设备中.它向系统发送伪随机的用户事件流(如按键输入.触摸屏输入.手势输入等),实现对正在开发的应用程序进行压力测试.Monkey ...

  3. Linux时间子系统之一:clock source(时钟源)【转】

    转自:http://blog.csdn.net/droidphone/article/details/7975694 clock source用于为linux内核提供一个时间基线,如果你用linux的 ...

  4. centos6.5升级Linux内核步骤

    centos6.5升级Linux内核步骤 http://www.jianshu.com/p/c75f00182b4c 使用的操作系统是是centos6.5,按照官方的推荐的配置,把linux内核升级到 ...

  5. javascript方法--apply()

    今天琢磨了一下apply,以前对这个方法觉得比较懵,今天一琢磨确实觉得挺好玩的. 一开始把MDN的apply文档看了一遍,感觉不是很理解,而且有一些东西也是知道但是比较模糊,所以还是一步一步来,不懂查 ...

  6. java 默认内存大小

    https://www.cnblogs.com/jack204/archive/2012/07/02/2572932.html -Xmx   Java Heap最大值,默认值为物理内存的1/4,最佳设 ...

  7. Python基础系列----语法、数据类型、变量、编码

    1.基本语法                                                                                        Python ...

  8. C# For Bot Framework

    Bot Framework是一个聊天机器人的框架,背后是微软的SDK,它可以使用C#和Nodejs开发,今天我尝试用创建一个比较简单Bot 参考地址:https://docs.microsoft.co ...

  9. SQL练习总结

    [SQL语句练习] 1. 表1: Person +-------------+---------+ | 列名 | 类型 | +-------------+---------+ | PersonId | ...

  10. Luogu P2146 软件包管理器(树链剖分+线段树)

    题意 给定\(n\)个软件包,每个软件包都有一个依赖软件包,安装一个软件包必须安装他的依赖软件包,卸载一个软件包必须先卸载所有依赖于它的软件包.给定\(m\)此操作,每次一个操作\(install/u ...