1. 题目描述
当一个结点lightning后,可以向其周围距离小于等于R的结点传播lightning。然后以该结点为中心继续传播。以此类推,
问最终形成的树形结构有多少个。
2. 基本思路
生成树级数模板题目。
Matrix-Tree定理(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。
定义Kirchhoff矩阵C[G] = D[G]-A[G]。不同生成树的个数是C[G]的任何一个n-1阶主子式的行列式的绝对值。
行列式值通过化上三角可求。除法使用逆元可求。
3. 代码
1 /* 4305 */ 2 #include <iostream> 3 #include <sstream> 4 #include <string> 5 #include <map> 6 #include <queue> 7 #include <set> 8 #include <stack> 9 #include <vector> 10 #include <deque> 11 #include <bitset> 12 #include <algorithm> 13 #include <cstdio> 14 #include <cmath> 15 #include <ctime> 16 #include <cstring> 17 #include <climits> 18 #include <cctype> 19 #include <cassert> 20 #include <functional> 21 #include <iterator> 22 #include <iomanip> 23 using namespace std; 24 //#pragma comment(linker,"/STACK:102400000,1024000") 25 26 #define sti set<int> 27 #define stpii set<pair<int, int> > 28 #define mpii map<int,int> 29 #define vi vector<int> 30 #define pii pair<int,int> 31 #define vpii vector<pair<int,int> > 32 #define rep(i, a, n) for (int i=a;i<n;++i) 33 #define per(i, a, n) for (int i=n-1;i>=a;--i) 34 #define clr clear 35 #define pb push_back 36 #define mp make_pair 37 #define fir first 38 #define sec second 39 #define all(x) (x).begin(),(x).end() 40 #define SZ(x) ((int)(x).size()) 41 #define lson l, mid, rt<<1 42 #define rson mid+1, r, rt<<1|1 43 44 typedef struct Point { 45 int x, y; 46 47 Point() {} 48 Point(int x, int y): 49 x(x), y(y) {} 50 51 Point operator - (const Point& a) const { 52 return Point(x-a.x, y-a.y); 53 } 54 55 int operator ^ (const Point& a) const { 56 return x*a.y - y*a.x; 57 } 58 59 } Point; 60 61 typedef struct Segment { 62 Point s, e; 63 64 Segment() {} 65 Segment(Point s, Point e): 66 s(s), e(e) {} 67 68 } Segment; 69 70 bool onSegment(Point p, Point a, Point b) { 71 return ((a-p)^(b-p))==0 && (p.x-a.x)*(p.x-b.x)<=0 && (p.y-a.y)*(p.y-b.y)<=0; 72 } 73 74 int Length(Point a, Point b) { 75 return (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y); 76 } 77 78 79 #define LL __int64 80 81 const int mod = 10007; 82 83 84 LL Pow(LL base, LL n, LL mod) { 85 LL ret = 1; 86 87 while (n) { 88 if (n & 1) 89 ret = ret * base % mod; 90 base = base * base % mod; 91 n >>= 1; 92 } 93 94 return ret; 95 } 96 97 int Inv(int x) { 98 return Pow(x, mod-2, mod); 99 } 100 101 typedef struct mat_t { 102 static const int maxn = 305; 103 int m[maxn][maxn]; 104 105 void init() { 106 memset(m, 0, sizeof(m)); 107 } 108 109 int det(int n) { 110 rep(i, 0, n) 111 rep(j, 0, n) 112 m[i][j] = (m[i][j]%mod+mod) % mod; 113 int ret = 1; 114 115 rep(i, 0, n) { 116 rep(j, i, n) { 117 if (m[j][i]) { 118 rep(k, i, n) 119 swap(m[i][k], m[j][k]); 120 if (i != j) 121 ret = (-ret + mod) % mod; 122 break; 123 } 124 } 125 126 if (m[i][i] == 0) { 127 ret = -1; 128 break; 129 } 130 131 rep(j, i+1, n) { 132 int tmp = m[j][i] * Inv(m[i][i]) % mod; 133 rep(k, i, n) 134 m[j][k] = ((m[j][k] - m[i][k]*tmp%mod) % mod + mod) % mod; 135 } 136 137 ret = ret * m[i][i] % mod; 138 } 139 140 return ret; 141 } 142 } mat_t; 143 144 const int maxn = 305; 145 Point P[maxn]; 146 int n, R, R2; 147 bool M[maxn][maxn]; 148 mat_t base; 149 150 bool judge(int i, int j) { 151 if (Length(P[i], P[j]) > R2) 152 return false; 153 154 rep(k, 0, n) { 155 if (k==i || k==j) 156 continue; 157 158 if (onSegment(P[k], P[i], P[j])) 159 return false; 160 } 161 162 return true; 163 } 164 165 void solve() { 166 R2 = R * R; 167 168 memset(M, false, sizeof(M)); 169 rep(i, 0, n) { 170 rep(j, i+1, n) { 171 if (judge(i, j)) 172 M[i][j] = M[j][i] = true; 173 } 174 } 175 176 base.init(); 177 rep(i, 0, n) { 178 rep(j, 0, n) { 179 if (i==j || !M[i][j]) 180 continue; 181 182 ++base.m[i][i]; 183 base.m[i][j] = -1; 184 } 185 } 186 187 int ans = base.det(n-1); 188 189 printf("%d\n", ans); 190 } 191 192 int main() { 193 ios::sync_with_stdio(false); 194 #ifndef ONLINE_JUDGE 195 freopen("data.in", "r", stdin); 196 freopen("data.out", "w", stdout); 197 #endif 198 199 int t; 200 201 scanf("%d", &t); 202 while (t--) { 203 scanf("%d %d", &n, &R); 204 rep(i, 0, n) 205 scanf("%d %d", &P[i].x, &P[i].y); 206 solve(); 207 } 208 209 #ifndef ONLINE_JUDGE 210 printf("time = %d.\n", (int)clock()); 211 #endif 212 213 return 0; 214 }
4. 数据发生器
1 import sys 2 import string 3 from random import randint 4 5 6 def GenData(fileName): 7 with open(fileName, "w") as fout: 8 t = 20 9 bound = 10**4 10 fout.write("%d\n" % (t)) 11 for tt in xrange(t): 12 n = randint(1, 300) 13 r = randint(0, 20000) 14 fout.write("%d %d\n" % (n, r)) 15 for i in xrange(n): 16 x = randint(-bound, bound) 17 y = randint(-bound, bound) 18 fout.write("%d %d\n" % (x, y)) 19 20 21 def MovData(srcFileName, desFileName): 22 with open(srcFileName, "r") as fin: 23 lines = fin.readlines() 24 with open(desFileName, "w") as fout: 25 fout.write("".join(lines)) 26 27 28 def CompData(): 29 print "comp" 30 srcFileName = "F:\Qt_prj\hdoj\data.out" 31 desFileName = "F:\workspace\cpp_hdoj\data.out" 32 srcLines = [] 33 desLines = [] 34 with open(srcFileName, "r") as fin: 35 srcLines = fin.readlines() 36 with open(desFileName, "r") as fin: 37 desLines = fin.readlines() 38 n = min(len(srcLines), len(desLines))-1 39 for i in xrange(n): 40 ans2 = int(desLines[i]) 41 ans1 = int(srcLines[i]) 42 if ans1 > ans2: 43 print "%d: wrong" % i 44 45 46 if __name__ == "__main__": 47 srcFileName = "F:\Qt_prj\hdoj\data.in" 48 desFileName = "F:\workspace\cpp_hdoj\data.in" 49 GenData(srcFileName) 50 MovData(srcFileName, desFileName) 51 52
基本思路