├── README.md └── main.cpp /README.md: -------------------------------------------------------------------------------- 1 | # 2020华为软件精英挑战赛 2 | 3 | 由于平台太迷弃坑。5分代码。 4 | 5 | 问题:给一个有向图,问有多少个长度在3-7的简单环。 6 | 7 | # 思路 8 | ID离散化(`hh, disc`)。 9 | 10 | 深搜找出距离每个点正走3步以内的点和倒走3步以内的点(`dfs3`)。 11 | 12 | 枚举一条边(x, y),满足x < y则枚举$$(b_x(1), f_y(1)), (b_x(1), f_y(2)),(b_x(1), f_y(3)),(b_x(2), f_y(3)),(b_x(3), f_y(3))$$中相同的点z(`checksame`)。其中$b_a(k)$为a为起点反走有向边k步,$f_a(k)$为a为起点正走有向边k步。 13 | 14 | 找出所有(z -> x), (y -> z)的路径(`getroute`),乘法原理组合,同时检查是否满足x为全环最小,环为简单环。如果是,加入结果集合(`push_to_res`)。 15 | 16 | 结果集合排序输出。 17 | 18 | # 可优化点 19 | - 删去不在环上的点 20 | - listf可以只保留比当前点大的 21 | - getroute可以提前删去包含过小点的情况,减少枚举 22 | - listf, listr相关的dfs3, getroute思路优化 23 | - checksame时,(0,2)(1,1)(2,0)之类的等价,可以选少的check 24 | - 枚举边按照从小到大,可以省了最后的排序 25 | - dfs可以换成bfs减少重复 26 | - 枚举边找环和dfs可以多线程 27 | - STL代码的优化 28 | - 输入输出优化 29 | - 离散化代码优化 30 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define OFFSET 20 7 | #define N 567890 8 | 9 | #define VECSORT(X) std::sort(X.begin(), X.end()) 10 | 11 | // #define Input "t.in" 12 | // #define Output "t.out" 13 | #define Input "/data/test_data.txt" 14 | #define Output "/projects/student/result.txt" 15 | 16 | 17 | struct tre { 18 | long long x, y, z; 19 | tre(long long x, long long y, long long z) : x(x), y(y), z(z) {} 20 | bool operator< (tre k) const { 21 | return x < k.x || 22 | x == k.x && y < k.y || 23 | x == k.x && y == k.y && z < k.z; 24 | } 25 | long long operator[] (int k) { 26 | return k == 0 ? x : k == 1 ? y : z; 27 | } 28 | }; 29 | 30 | std::vector res, data; 31 | std::vector disc, stack; 32 | std::vector> hh; 33 | int visit[N]; 34 | 35 | // void dfs(int k, int depth){//std::cout << k << ' ' << depth << '\n'; 36 | // visit[k] = depth; 37 | // stack.push_back(k); 38 | // for (auto i : edge[k]) 39 | // if (visit[i] && stack[visit[i]] == i){ 40 | // int len = visit[k] - visit[i] + 1; 41 | // if (len >= 3 && len <= 7){ 42 | // int start = depth; 43 | // for (int j = visit[i]; j < depth; j ++ ) 44 | // if (stack[j] < stack[start]) 45 | // start = j; 46 | // start -= visit[i]; 47 | // long long arr[3] = {0}; 48 | // arr[0] = len * 1LL << (OFFSET * 2); 49 | // //std::cout << start << ',' << depth << ' ' << len << ' '; 50 | // for (int j = 0; j < len; j ++ ){ 51 | // long long num = stack[visit[i] + (j + start) % len]; 52 | // //std::cout << num << ' '; 53 | // int index = (j + 1) / 3, move = 2 - (j + 1) % 3; 54 | // arr[index] += num << (OFFSET * move); 55 | // } 56 | // //std:: cout << arr[0] << ',' << arr[1] << ',' << arr[2] << '\n'; 57 | // res.push_back(tre(arr[0], arr[1], arr[2])); 58 | // } 59 | // } 60 | // else if (!visit[i]) dfs(i, depth + 1); 61 | // stack.pop_back(); 62 | // } 63 | 64 | std::vector>> listf[N], listr[N]; 65 | std::vector>>* list; 66 | std::vector edgef[N], edger[N]; 67 | std::vector* edge; 68 | 69 | void dfs3(int K) { 70 | list[K].resize(3); 71 | //TODO: change to bfs 72 | for (auto i : edge[K]) { 73 | list[K][0].push_back(std::make_pair(i, 0)); 74 | for (auto j : edge[i]) { 75 | if (j == K) continue; 76 | list[K][1].push_back(std::make_pair(j, i)); 77 | for (auto k : edge[j]) { 78 | if (k == K || k == i) continue; 79 | list[K][2].push_back(std::make_pair(k, j)); 80 | } 81 | } 82 | } 83 | VECSORT(list[K][0]); 84 | VECSORT(list[K][1]); 85 | VECSORT(list[K][2]); 86 | for (auto& i : list[K][1]) 87 | i.second = std::lower_bound(list[K][0].begin(), list[K][0].end(), i.second, 88 | [](std::pair x, int y) { return x.first < y; }) - list[K][0].begin(); 89 | for (auto& i : list[K][2]) 90 | i.second = std::lower_bound(list[K][1].begin(), list[K][1].end(), i.second, 91 | [](std::pair x, int y) { return x.first < y; }) - list[K][1].begin(); 92 | } 93 | 94 | std::vector> getroute(int k, int i, int j, std::vector>>* list) { 95 | // printf("gr: %d %d %d %s\n", k, i, j, list == listf ? "forward" : "backward"); 96 | std::vector> ret; 97 | if (i == -1) { 98 | std::vector v; 99 | v.push_back(k); 100 | ret.push_back(v); 101 | return ret; 102 | } 103 | int first = list[k][i][j].first; 104 | for (int q = j; q < list[k][i].size() && list[k][i][q].first == first; q++) { 105 | if (q != j && list[k][i][q].second == list[k][i][q - 1].second) continue; 106 | auto deep = getroute(k, i - 1, list[k][i][q].second, list); 107 | for (auto& i : deep) { 108 | i.push_back(first); 109 | ret.push_back(i); 110 | } 111 | } 112 | return ret; 113 | } 114 | 115 | void push_to_res(int len, long long* arr) { 116 | // std::cout << "PR: " << len << ' '; 117 | // for (int i = 0; i < len; i++) std::cout << arr[i] << ' '; std::cout << '\n'; 118 | long long tarr[3] = { 0 }; 119 | tarr[0] = len * 1LL << (OFFSET * 2); 120 | for (int j = 0; j < len; j++) { 121 | int index = (j + 1) / 3, move = 2 - (j + 1) % 3; 122 | tarr[index] += arr[j] << (OFFSET * move); 123 | } 124 | res.push_back(tre(tarr[0], tarr[1], tarr[2])); 125 | } 126 | 127 | void checksame(int kx, int ix, int ky, int iy) { 128 | // printf("cs: %d %d %d %d\n", kx, ix, ky, iy); 129 | for (int p1 = 0, p2 = 0; p1 < listr[kx][ix].size() && p2 < listf[ky][iy].size(); ) { 130 | int f1 = listr[kx][ix][p1].first, f2 = listf[ky][iy][p2].first; 131 | if (f1 > kx&& f2 > kx) 132 | if (f1 == f2) { 133 | auto xroute = getroute(kx, ix, p1, listr), yroute = getroute(ky, iy, p2, listf); 134 | for (auto& i : xroute) 135 | for (auto& j : yroute) { 136 | // for (auto a : i) std::cout << a; std::cout << '|'; 137 | // for (auto a : j) std::cout << a; std::cout << '\n'; 138 | bool same = 0; 139 | for (int ii = 0; ii < i.size() - 1; ii++) 140 | for (int jj = 0; jj < j.size() - 1; jj++) 141 | same += i[ii] == j[jj]; 142 | for (int ii = 1; ii < i.size() - 1; ii++) 143 | same += i[ii] <= kx; 144 | for (int jj = 1; jj < j.size() - 1; jj++) 145 | same += j[jj] <= kx; 146 | same += i.size() == 4 && i[1] == i[3]; 147 | same += j.size() == 4 && j[1] == j[3]; 148 | 149 | if (same) continue; 150 | std::vector num; 151 | num.push_back(kx); 152 | for (auto q : j) 153 | num.push_back(q); 154 | for (int q = i.size() - 2; q > 0; q--) 155 | num.push_back(i[q]); 156 | push_to_res(num.size(), &num[0]); 157 | } 158 | } 159 | if (f1 <= f2) for (; p1 < listr[kx][ix].size() && listr[kx][ix][p1].first == f1; p1++); 160 | if (f1 >= f2) for (; p2 < listf[ky][iy].size() && listf[ky][iy][p2].first == f2; p2++); 161 | } 162 | } 163 | 164 | int main() { 165 | freopen(Input, "r", stdin); 166 | freopen(Output, "w", stdout); 167 | stack.push_back(0); 168 | disc.push_back(0); 169 | int x, y, z; 170 | while (~scanf("%d,%d,%d", &x, &y, &z)) { 171 | data.push_back(tre(x, y, z)); 172 | hh.push_back(std::make_pair(x, data.size() * 2 - 2)); 173 | hh.push_back(std::make_pair(y, data.size() * 2 - 1)); 174 | } 175 | //for (auto i : hh) std::cout << i.first << ',' << i.second << ' ';std::cout << '\n'; 176 | VECSORT(hh); 177 | //for (auto i : hh) std::cout << i.first << ',' << i.second << ' ';std::cout << '\n'; 178 | for (int i = 0; i < hh.size(); i++) { 179 | if (!i || hh[i].first != hh[i - 1].first) { 180 | disc.push_back(hh[i].first); 181 | } 182 | int index = hh[i].second / 2, isy = hh[i].second % 2; 183 | (isy ? data[index].y : data[index].x) = disc.size() - 1; 184 | } 185 | //for (auto i : disc) std::cout << i << ' ';std::cout << '\n'; 186 | //for (auto i : data) std::cout << i.x << ',' << i.y << ',' << i.z << '\n'; std::cout << '\n'; 187 | for (auto i : data) { 188 | edgef[i.x].push_back(i.y); 189 | edger[i.y].push_back(i.x); 190 | } 191 | 192 | // for (auto i : edgef) VECSORT(i); 193 | // for (auto i : edger) VECSORT(i); 194 | // for (int i = 1; i < disc.size(); i ++ ) 195 | // if (!visit[i]) dfs(i, 1); 196 | 197 | // std::cout << "1\n"; 198 | list = listf; 199 | edge = edgef; 200 | for (int i = 1; i < disc.size(); i++) dfs3(i); 201 | list = listr; 202 | edge = edger; 203 | for (int i = 1; i < disc.size(); i++) dfs3(i); 204 | // std::cout << "2\n"; 205 | 206 | for (auto& i : data) { 207 | if (i.x < i.y) { 208 | // std::cout << "edge: " << i.x << i.y << '\n'; 209 | checksame(i.x, 0, i.y, 0); 210 | checksame(i.x, 0, i.y, 1); 211 | checksame(i.x, 0, i.y, 2); 212 | checksame(i.x, 1, i.y, 2); 213 | checksame(i.x, 2, i.y, 2); 214 | } 215 | } 216 | // std::cout << "3\n"; 217 | 218 | VECSORT(res); 219 | //for (auto i : res) std::cout << i.x << ',' << i.y << ',' << i.z << ' '; std::cout << '\n'; 220 | printf("%d\n", (int)res.size()); 221 | for (auto i : res) { 222 | int len = i.x >> (OFFSET * 2); 223 | for (int j = 1; j <= len; j++) { 224 | int index = j / 3, move = 2 - j % 3; 225 | printf("%d", disc[(i[index] >> (OFFSET * move))& ((1 << OFFSET) - 1)]); 226 | putchar(j == len ? '\n' : ','); 227 | } 228 | } 229 | } --------------------------------------------------------------------------------