hdu 4305 Lightning
http://acm.hdu.edu.cn/statistic.php?pid=4305&from=126&lang=&order_type=0
生成树计数加上极角排序,开始的时候忘记了计算过程中,数值会变成负数,所以wa了一次。生成树计数的矩阵运算必须注意,最后答案应该将它调整为整数。
题意是有n(n<=300)个人,如果某个人被电了,在他附近r范围内的人都会被电,算出被电的人形成的图案的种类数。两个能传递的人之间的直线位置不能有第三个人。
1800+ms的代码。。。囧:
View Code
1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 #include <cmath> 5 6 using namespace std; 7 8 const int maxn = 305; 9 const int maxSize = 305; 10 const int initMod = 10007; 11 const double eps = 1e-12; 12 int curSize = maxSize; 13 14 struct point { 15 int x; 16 int y; 17 int id; 18 19 bool operator == (point &a) const { 20 return x == a.x && y == a.y; 21 } 22 } pt[maxn], p0, buf[maxn]; 23 24 int dis2(point &a, point &b) { 25 int dx = a.x - b.x; 26 int dy = a.y - b.y; 27 28 return dx * dx + dy * dy; 29 } 30 31 bool cmp(point a, point b) { 32 if (a == p0) return true; 33 if (b == p0) return false; 34 35 double tmp = atan2(a.y - p0.y, a.x - p0.x) - atan2(b.y - p0.y, b.x - p0.x); 36 37 if (fabs(tmp) < eps) return dis2(a, p0) < dis2(b, p0); 38 return tmp < 0; 39 } 40 41 struct Mat { 42 int val[maxSize][maxSize]; 43 44 Mat () { 45 for (int i = 0; i < curSize; i++) { 46 for (int j = 0; j < curSize; j++) { 47 val[i][j] = 0; 48 } 49 } 50 } 51 int det() { 52 int ret = 1; 53 54 for (int p = 1; p < curSize; p++) { 55 for (int i = p + 1; i < curSize; i++) { 56 while (val[i][p]) { 57 int k = val[p][p] / val[i][p]; 58 59 for (int j = p; j < curSize; j++) { 60 val[p][j] = (val[p][j] - val[i][j] * (k % initMod)) % initMod; 61 swap(val[p][j], val[i][j]); 62 } 63 ret = -ret; 64 } 65 } 66 ret *= val[p][p]; 67 ret = (ret % initMod + initMod) % initMod; 68 } 69 70 return ret; 71 } 72 void print() { 73 for (int i = 0; i < curSize; i++) { 74 for (int j = 0; j < curSize; j++) { 75 printf("%d ", val[i][j]); 76 } 77 puts(""); 78 } 79 puts("~~~"); 80 } 81 } mat; 82 83 void input(int n) { 84 for (int i = 0; i < n; i++) { 85 scanf("%d%d", &pt[i].x, &pt[i].y); 86 pt[i].id = i; 87 buf[i] = pt[i]; 88 } 89 } 90 91 bool diffLine(point &a, point &p, point &b) { 92 return fabs(atan2(a.y - p.y, a.x - p.x) - atan2(b.y - p.y, b.x - p.x)) > eps; 93 } 94 95 void addEdge(int &a, int &b) { 96 mat.val[a][b]--; 97 mat.val[a][a]++; 98 } 99 100 void makeMat(int n, int r) { 101 mat = Mat(); 102 for (int i = 0; i < n; i++) { 103 p0 = buf[i]; 104 sort(pt, pt + n, cmp); 105 if (dis2(pt[1], p0) <= r) { 106 addEdge(pt[1].id, p0.id); 107 } 108 for (int j = 2; j < n; j++) { 109 if (diffLine(pt[j - 1], p0, pt[j])) { 110 if (dis2(pt[j], p0) <= r) { 111 addEdge(pt[j].id, p0.id); 112 } 113 } 114 } 115 // for (int j = 0; j < n; j++) { 116 // printf("%d %d\n", pt[j].x, pt[j].y); 117 // } 118 // puts("~~~"); 119 } 120 // mat.print(); 121 // puts("!!!"); 122 } 123 124 bool vis[maxn]; 125 126 void dfs(int x) { 127 128 for (int i = 0; i < curSize; i++) { 129 if (vis[i]) continue; 130 if (mat.val[x][i]) { 131 vis[i] = true; 132 dfs(i); 133 } 134 } 135 } 136 137 bool check(int n) { 138 memset(vis, false, sizeof(vis)); 139 vis[0] = true; 140 dfs(0); 141 for (int i = 0; i < n; i++) { 142 if (!vis[i]) return false; 143 } 144 145 return true; 146 } 147 148 int main() { 149 int T; 150 int n, m; 151 152 // freopen("in", "r", stdin); 153 scanf("%d", &T); 154 while (T--) { 155 scanf("%d%d", &n, &m); 156 curSize = n; 157 input(n); 158 makeMat(n, m * m); 159 160 if (check(n)) { 161 int ans = mat.det(); 162 163 printf("%d\n", ans); 164 } else puts("-1"); 165 } 166 167 return 0; 168 }
——written by Lyon