标签:des style blog http color java 使用 os
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1457 Accepted Submission(s): 469
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\n",ans?ans:-1); 109 } 110 return 0; 111 }
hdu 4305 生成树奇数问题,布布扣,bubuko.com
标签:des style blog http color java 使用 os
原文地址:http://www.cnblogs.com/xiong-/p/3925207.html