hdu 4305 生成树计数问题

Lightning

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


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
 

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]表示。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cmath>
  5 using namespace std;
  6 
  7 typedef _int64 LL;
  8 const int maxn=305;
  9 const int MOD=10007;
 10 int n,R;
 11 int g[maxn][maxn],d[maxn][maxn],mat[maxn][maxn];//邻接矩阵,度数矩阵,D-G矩阵
 12 
 13 struct Point
 14 {
 15     int x,y;
 16     Point(int x=0,int y=0):x(x),y(y){}
 17 }p[maxn];
 18 typedef Point Vector;
 19 Vector operator -(Vector A,Vector B){return Vector(A.x-B.x,A.y-B.y);}
 20 int Dot(Vector A,Vector B){ return A.x*B.x+A.y*B.y;}//点积
 21 int Cross(Vector A,Vector B){ return A.x*B.y-A.y*B.x;}//叉积
 22 int Length2(Vector A){return Dot(A,A);}//向量模的平方
 23 bool OnSegment(Point p,Point a1,Point a2)//点是否在直线上(不包括端点)
 24 {
 25     return Cross(a1-p,a2-p)==0 && Dot(a1-p,a2-p)<0;
 26 }
 27 
 28 LL Extended_Euclid(LL a,LL b,LL &x,LL &y)
 29 {
 30     LL d,t;
 31     if(b==0){x=1;y=0;return a;}
 32     d=Extended_Euclid(b,a%b,x,y);
 33     t=x;x=y;y=t-a/b*y;
 34     return d;
 35 }
 36 LL inv(LL a,LL n)//计算模n下a的逆,若不存在逆返回-1
 37 {
 38     LL d,x,y;
 39     d=Extended_Euclid(a,n,x,y);
 40     return d==1?(x+n)%n:-1;
 41 }
 42 int Det(int n)//求行列式的值模上MOD,需要使用逆元
 43 {
 44     int i,j,k,ret=1;
 45     for(i = 0;i < n;i++)
 46     for(j = 0;j < n;j++)
 47         mat[i][j] = (mat[i][j]%MOD+MOD)%MOD;
 48     for(i = 0;i < n;i++)    
 49     {
 50         for(j = i;j < n;j++)
 51         if(mat[j][i]!=0)
 52         {
 53             for(k = i;k < n;k++) swap(mat[i][k],mat[j][k]);
 54             if(i != j) ret = (-ret+MOD)%MOD;
 55             break;
 56         }
 57         if(mat[i][i]==0)
 58         {
 59             ret=0;break;
 60         }
 61         for(j=i+1;j<n;j++)
 62         {
 63             int mut=(mat[j][i]*inv(mat[i][i],MOD))%MOD;
 64             for(k=i;k<n;k++)
 65                 mat[j][k]=(mat[j][k]-(mat[i][k]*mut)%MOD+MOD)%MOD;
 66         }
 67         ret=(ret*mat[i][i])%MOD;
 68     }
 69     return ret;
 70 }
 71 
 72 void build_graph()
 73 {
 74     memset(g,0,sizeof(g));
 75     memset(d,0,sizeof(d));
 76     int i,j,k;
 77     for(i=0;i<n;i++)
 78     {
 79         for(j=i+1;j<n;j++)
 80         {
 81             if(Length2(p[j]-p[i])>R*R) continue;
 82             bool flag=1;
 83             for(k=0;k<n;k++)
 84                 if(OnSegment(p[k],p[i],p[j])){flag=0;break;}
 85             if(flag){ g[i][j]=g[j][i]=1;d[i][i]++;d[j][j]++;}
 86         }
 87     }
 88 }
 89 
 90 void get_DGMatrix()
 91 {
 92     for(int i=0;i<n;i++)
 93     for(int j=0;j<n;j++)
 94         mat[i][j]=d[i][j]-g[i][j];
 95 }
 96 
 97 int main()
 98 {
 99     int t,i;
100     scanf("%d",&t);
101     while(t--)
102     {
103         scanf("%d%d",&n,&R);
104         for(i=0;i<n;i++) scanf("%d%d",&p[i].x,&p[i].y);
105         build_graph();
106         get_DGMatrix();
107         int ans=Det(n-1);
108         printf("%d
",ans?ans:-1);
109     }
110     return 0;
111 }
原文地址:https://www.cnblogs.com/xiong-/p/3925207.html