总结 高精度加减乘除 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 #include <iostream> #include <string> #include <algorithm> using namespace std;string addLargeNumbers (string num1, string num2) { reverse (num1.begin (), num1.end ()); reverse (num2.begin (), num2.end ()); int n = max (num1.length (), num2.length ()); string sum (n, '0' ) ; int carry = 0 ; for (int i = 0 ; i < n; ++i) { int digit1 = i < num1.length () ? num1[i] - '0' : 0 ; int digit2 = i < num2.length () ? num2[i] - '0' : 0 ; int currentSum = digit1 + digit2 + carry; sum[i] = currentSum % 10 + '0' ; carry = currentSum / 10 ; } if (carry > 0 ) { sum.push_back (carry + '0' ); } reverse (sum.begin (), sum.end ()); return sum; } string multiply (string num1, string num2) { int n1 = num1.size (); int n2 = num2.size (); vector<int > result (n1 + n2, 0 ) ; for (int i = n1 - 1 ; i >= 0 ; --i) { for (int j = n2 - 1 ; j >= 0 ; --j) { int mul = (num1[i] - '0' ) * (num2[j] - '0' ); int sum = mul + result[i + j + 1 ]; result[i + j + 1 ] = sum % 10 ; result[i + j] += sum / 10 ; } } string resultStr; for (int num : result) { if (!(resultStr.empty () && num == 0 )) { resultStr.push_back (num + '0' ); } } return resultStr.empty () ? "0" : resultStr; } bool isSmaller (string num1, string num2) { int n1 = num1.length (), n2 = num2.length (); if (n1 < n2) return true ; if (n2 < n1) return false ; for (int i = 0 ; i < n1; i++) { if (num1[i] < num2[i]) return true ; else if (num1[i] > num2[i]) return false ; } return false ; } string subtract (string num1, string num2) { string result; while (num1.length () < num2.length ()) num1 = "0" + num1; while (num2.length () < num1.length ()) num2 = "0" + num2; int carry = 0 ; for (int i = num1.length () - 1 ; i >= 0 ; i--) { int sub = ((num1[i]-'0' ) - (num2[i]-'0' ) - carry); if (sub < 0 ) { sub = sub + 10 ; carry = 1 ; } else { carry = 0 ; } result.insert (result.begin (), sub + '0' ); } while (result.length () > 1 && result[0 ] == '0' ) result.erase (result.begin ()); return result; } string subtractNumbers (string num1, string num2) { bool negative = false ; if (isSmaller (num1, num2)) { swap (num1, num2); negative = true ; } string result = subtract (num1, num2); if (negative) result.insert (result.begin (), '-' ); return result; } pair<string, int > divide (string A, int B) { string quotient; int remainder = 0 ; int n = A.length (); for (int i = 0 ; i < n; i++) { remainder = remainder * 10 + (A[i] - '0' ); quotient += (remainder / B) + '0' ; remainder %= B; } int start = 0 ; int l = quotient.length (); while (start < l && quotient[start] == '0' ) { start++; } if (start == l) { quotient = "0" ; } else { quotient = quotient.substr (start); } return {quotient, remainder}; } int main () { string num1, num2; cin >> num1 >> num2; cout << addLargeNumbers (num1, num2) << endl; cout << subtractNumbers (num1, num2) << endl; cout << multiply (num1, num2) << endl; auto [quotient, remainder] = divide (num1, stoi (num2)); cout << quotient << endl; cout << remainder << endl; return 0 ; }
Acwing 数据结构 包括单链表,双链表,栈,队列,单调栈,单调队列,KMP,Trie,并查集,堆,哈希表等内容。
826. 单链表 原题链接:https://www.acwing.com/problem/content/828/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 he #include <iostream> using namespace std;const int N = 100010 ;int head;int current;int value[N], next_node[N];void init () { head = 0 ; current = 1 ; } void add_k (int k, int x) { value[current] = x; next_node[current] = next_node[k]; next_node[k] = current++; } void del_k (int k) { next_node[k] = next_node[next_node[k]]; } int main () { init (); int m; cin >> m; while (m--) { char op; int k, x; cin >> op; if (op == 'H' ) { cin >> x; add_k (0 , x); } else if (op == 'I' ) { cin >> k >> x; add_k (k, x); } else { cin >> k; del_k (k); } cout << "\nValues:\n" ; for (int j = next_node[0 ]; j; j = next_node[j]) { cout << value[j] << ' ' ; } cout << endl; cout << "\nPointers:\n" ; for (int i = 0 ; i < 10 ; i++) { cout << next_node[i] << ' ' ; } cout << endl; } return 0 ; }
827. 双链表 原题链接:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 #include <iostream> using namespace std;const int N = 1e6 + 10 ; int value[N], prev_node[N], next_node[N], current; void insert (int k, int x) { value[current] = x; prev_node[current] = k; next_node[current] = next_node[k]; prev_node[next_node[k]] = current; next_node[k] = current++; } void remove (int k) { prev_node[next_node[k]] = prev_node[k]; next_node[prev_node[k]] = next_node[k]; } int main () { int m; cin >> m; next_node[0 ] = 1 ; prev_node[0 ] = 0 ; current = 2 ; while (m--) { string op; cin >> op; int k, x; if (op == "L" ) { cin >> x; insert (0 , x); } else if (op == "R" ) { cin >> x; insert (prev_node[1 ], x); } else if (op == "D" ) { cin >> k; remove (k + 1 ); } else if (op == "IL" ) { cin >> k >> x; insert (prev_node[k + 1 ], x); } else { cin >> k >> x; insert (k + 1 , x); } } for (int i = next_node[0 ]; i != 1 ; i = next_node[i]) cout << value[i] << ' ' ; cout << endl; return 0 ; }
828. 模拟栈 原题链接:https://www.acwing.com/problem/content/830/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 #include <iostream> using namespace std;const int N = 1e6 + 10 ;int stack[N], top;void push (int x) { stack[++top] = x; } void pop () { top--; } bool isempty () { bool ans; top ? ans = false : ans = true ; return ans; } int query () { return stack[top]; } int main () { int m; cin >> m; while (m--) { string op; int x; cin >> op; if (op == "push" ) { cin >> x; push (x); } else if (op == "pop" ) pop (); else if (op == "empty" ) cout << (isempty () ? "YES" : "NO" ) << endl; else cout << query () << endl; } return 0 ; }
829. 模拟队列 原题链接:https://www.acwing.com/problem/content/831/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 #include <iostream> using namespace std;const int MAX_SIZE = 100010 ; int m; int queue[MAX_SIZE]; int front_index, rear_index = -1 ; int main () { cin >> m; while (m--) { string op; int x; cin >> op; if (op == "push" ) { cin >> x; queue[++rear_index] = x; } else if (op == "pop" ) { front_index++; } else if (op == "empty" ) { cout << (front_index <= rear_index ? "NO" : "YES" ) << endl; } else { cout << queue[front_index] << endl; } } return 0 ; }
154. 滑动窗口 原题链接:https://www.acwing.com/problem/content/156/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 #include <iostream> #include <cstring> #include <algorithm> #include <deque> using namespace std;const int N = 1000010 ;int a[N];int main () { int n, k; cin >> n >> k; for (int i = 1 ; i <= n; i++) cin >> a[i]; deque<int > q; for (int i = 1 ; i <= n; i++) { while (q.size () && a[q.back ()] > a[i]) q.pop_back (); q.push_back (i); if (i - k >= 1 && q.front () == i - k) q.pop_front (); if (i >= k) cout << a[q.front ()] << " " ; } q.clear (); cout << endl; for (int i = 1 ; i <= n; i++) { while (q.size () && a[q.back ()] < a[i]) q.pop_back (); q.push_back (i); if (i - k >= 1 && q.front () == i - k) q.pop_front (); if (i >= k) cout << a[q.front ()] << " " ; } return 0 ; }
3302. 表达式求值 原题链接:https://www.acwing.com/problem/content/3305/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 #include <iostream> #include <stack> #include <string> #include <unordered_map> using namespace std;stack<int > num; stack<char > op; unordered_map<char , int > h{ {'+' , 1 }, {'-' , 1 }, {'*' ,2 }, {'/' , 2 } }; void eval () { int a = num.top (); num.pop (); int b = num.top (); num.pop (); char p = op.top (); op.pop (); int r = 0 ; if (p == '+' ) r = b + a; if (p == '-' ) r = b - a; if (p == '*' ) r = b * a; if (p == '/' ) r = b / a; num.push (r); } int main () { string s; cin >> s; for (int i = 0 ; i < s.size (); i++) { if (isdigit (s[i])) { int x = 0 , j = i; while (j < s.size () && isdigit (s[j])) { x = x * 10 + s[j] - '0' ; j++; } num.push (x); i = j - 1 ; } else if (s[i] == '(' ) { op.push (s[i]); } else if (s[i] == ')' ) { while (op.top () != '(' ) eval (); op.pop (); } else { while (op.size () && h[op.top ()] >= h[s[i]]) eval (); op.push (s[i]); } } while (op.size ()) eval (); cout << num.top () << endl; return 0 ; }
836. 合并集合 原题链接:https://www.acwing.com/problem/content/838/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 #include <iostream> using namespace std;const int N = 1e5 + 10 ; int set[N]; int find (int x) { if (set[x] != x) set[x] = find (set[x]); return set[x]; } int main () { int n, m; cin >> n >> m; for (int i = 1 ; i <= n; i++) { set[i] = i; } for (int i = 1 ; i <= m; i++) { char op[2 ]; int a, b; cin >> op >> a >> b; if (*op == 'M' ) { set[find (a)] = find (b); } else { if (find (a) == find (b)) { cout << "Yes\n" ; } else { cout << "No\n" ; } } } return 0 ; }
837. 连通块中点的数量 原题链接:https://www.acwing.com/problem/content/839/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 #include <iostream> using namespace std;const int N = 100010 ; int n, m; int p[N], cnt[N]; int find (int x) { if (p[x] != x) p[x] = find (p[x]); return p[x]; } int main () { cin >> n >> m; for (int i = 1 ; i <= n; i++) { p[i] = i; cnt[i] = 1 ; } while (m--) { string op; int a, b; cin >> op; if (op == "C" ) { cin >> a >> b; a = find (a), b = find (b); if (a != b) { p[a] = b; cnt[b] += cnt[a]; } } else if (op == "Q1" ) { cin >> a >> b; if (find (a) == find (b)) puts ("Yes" ); else puts ("No" ); } else { cin >> a; cout << cnt[find (a)] << endl; } } return 0 ; }
240. 食物链 原题链接:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 #include <iostream> using namespace std;const int N = 50010 ;int n, m;int p[N], d[N];int find (int x) { if (p[x] != x) { int t = find (p[x]); d[x] += d[p[x]]; p[x] = t; } return p[x]; } int main () { scanf ("%d%d" , &n, &m); for (int i = 1 ; i <= n; i ++ ) p[i] = i; int res = 0 ; while (m--) { int t, x, y; scanf ("%d%d%d" , &t, &x, &y); if (x > n || y > n) res++ ; else { int px = find (x), py = find (y); if (t == 1 ) { if (px == py && (d[x] - d[y]) % 3 ) res++ ; else if (px != py) { p[px] = py; d[px] = d[y] - d[x]; } } else { if (px == py && (d[x] - d[y] - 1 ) % 3 ) res++ ; else if (px != py) { p[px] = py; d[px] = d[y] + 1 - d[x]; } } } } printf ("%d\n" , res); return 0 ; }
838. 堆排序 原题链接:https://www.acwing.com/problem/content/840/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 #include <iostream> #include <algorithm> using namespace std;const int N = 100010 ;int h[N], mySize;int n, m;void down (int u) { int t = u; if (2 * u <= mySize && h[t] > h[2 * u]) t = 2 * u; if (2 * u + 1 <= mySize && h[t] > h[2 * u + 1 ]) t = 2 * u + 1 ; if (u != t) { swap (h[u], h[t]); down (t); } } int main () { cin >> n >> m; mySize = n; for (int i = 1 ; i <= n; i++) scanf ("%d" , &h[i]); for (int i = n / 2 ; i; i--) down (i); while (m--) { cout << h[1 ] << " " ; h[1 ] = h[mySize--]; down (1 ); } return 0 ; }
839. 模拟堆 原题链接:https://www.acwing.com/problem/content/841/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 #include <iostream> using namespace std;int const maxn = 1e5 + 10 ;int h[maxn], kp[maxn], pk[maxn], idx, len;void h_swap (int a, int b) { swap (h[a], h[b]); swap (pk[a], pk[b]); swap (kp[pk[a]], kp[pk[b]]); } void down (int u) { int t = u; if (2 * u <= len && h[u * 2 ] < h[t]) t = u * 2 ; if (2 * u + 1 <= len && h[u * 2 + 1 ] < h[t]) t = u * 2 + 1 ; if (t != u) { h_swap (t, u); down (t); } } void up (int u) { int t = u; if (u / 2 > 0 && h[u / 2 ] > h[t]) t = u / 2 ; if (t != u) { h_swap (t, u); up (t); } } int main () { int n; cin >> n; while (n--) { string aim; cin >> aim; if (aim == "I" ) { int x; cin >> x; h[++len] = x; pk[len] = ++idx; kp[idx] = len; up (len); } else if (aim == "PM" ) { cout << h[1 ] << endl; } else if (aim == "DM" ) { h_swap (1 , len--); down (1 ); } else if (aim == "D" ) { int k; cin >> k; int u = kp[k]; h_swap (kp[k], len--); up (u); down (u); } else if (aim == "C" ) { int k, x; cin >> k >> x; h[kp[k]] = x; up (kp[k]); down (kp[k]); } } }
831. KMP字符串 原题链接:https://www.acwing.com/problem/content/833/ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 #include <iostream> using namespace std;const int N = 100010 , M = 1000010 ;int n, m;int ne[N];char s[M], p[N];int main () { cin >> n >> (p + 1 ) >> m >> (s + 1 ); for (int i = 2 , j = 0 ; i <= n; i++ ) { while (j && p[i] != p[j + 1 ]) j = ne[j]; if (p[i] == p[j + 1 ]) j++ ; ne[i] = j; } for (int i = 1 , j = 0 ; i <= m; i++ ) { while (j && s[i] != p[j + 1 ]) j = ne[j]; if (s[i] == p[j + 1 ]) j++ ; if (j == n) { printf ("%d " , i - n); j = ne[j]; } } return 0 ; }
835. Trie字符串统计 原题链接:https://www.acwing.com/problem/content/837/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 #include <iostream> using namespace std;const int N = 1e5 + 10 ; int son[N][26 ], cnt[N], index; char str[N]; void insert (char *str) { int p = 0 ; for (int i = 0 ; str[i]; i++) { int u = str[i] - 'a' ; if (!son[p][u]) { son[p][u] = ++index; } p = son[p][u]; } cnt[p]++; } int query (char *str) { int p = 0 ; for (int i = 0 ; str[i]; i++) { int u = str[i] - 'a' ; if (!son[p][u]) { return 0 ; } p = son[p][u]; } return cnt[p]; } int main () { int n; cin >> n; while (n--) { char op[2 ]; cin >> op >> str; if (*op == 'I' ) { insert (str); } else { cout << query (str) << endl; } } return 0 ; }
143. 最大异或对 原题链接:https://www.acwing.com/problem/content/145/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 #include <iostream> #include <algorithm> using namespace std;const int N = 1e5 + 10 , M = 31 * N;int n;int a[N], son[M][2 ], curr;void insert (int x) { int p = 0 ; for (int i = 30 ; i >= 0 ; i--) { int &s = son[p][x >> i & 1 ]; if (!s) s = ++curr; p = s; } } int search (int x) { int p = 0 , res = 0 ; for (int i = 30 ; i >= 0 ; i-- ) { int s = x >> i & 1 ; if (son[p][!s]) { res += 1 << i; p = son[p][!s]; } else p = son[p][s]; } return res; } int main () { scanf ("%d" , &n); for (int i = 0 ; i < n; i++ ) { scanf ("%d" , &a[i]); insert (a[i]); } int res = 0 ; for (int i = 0 ; i < n; i++ ) res = max (res, search (a[i])); printf ("%d\n" , res); return 0 ; }
840. 模拟散列表 原题链接:https://www.acwing.com/problem/content/842/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 #include <cstring> #include <iostream> using namespace std;const int HASH_SIZE = 100003 ; int hashTable[HASH_SIZE]; int elements[HASH_SIZE]; int nextIndex[HASH_SIZE]; int currentIndex; int operationCount; void insertElement (int x) { int hashValue = (x % HASH_SIZE + HASH_SIZE) % HASH_SIZE; elements[currentIndex] = x; nextIndex[currentIndex] = hashTable[hashValue]; hashTable[hashValue] = currentIndex++; } bool findElement (int x) { int hashValue = (x % HASH_SIZE + HASH_SIZE) % HASH_SIZE; for (int i = hashTable[hashValue]; i != -1 ; i = nextIndex[i]) { if (elements[i] == x) { return true ; } } return false ; } int main () { cin >> operationCount; memset (hashTable, -1 , sizeof hashTable); while (operationCount--) { string operation; int element; cin >> operation >> element; if (operation == "I" ) { insertElement (element); } else { if (findElement (element)) { puts ("Yes" ); } else { puts ("No" ); } } } return 0 ; }
841. 字符串哈希 原题链接:https://www.acwing.com/problem/content/843/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 #include <iostream> #include <string> using namespace std;const int MAX_LEN = 1e5 + 5 ; const int BASE = 131 ; typedef unsigned long long ULL; ULL prefixHash[MAX_LEN]; ULL basePower[MAX_LEN]; ULL calculateHash (int left, int right) { return prefixHash[right] - prefixHash[left - 1 ] * basePower[right - left + 1 ]; } int main () { int strLen, queryCount; cin >> strLen >> queryCount; string str; cin >> str; basePower[0 ] = 1 ; prefixHash[0 ] = 0 ; for (int i = 0 ; i < strLen; i++) { basePower[i + 1 ] = basePower[i] * BASE; prefixHash[i + 1 ] = prefixHash[i] * BASE + str[i]; } while (queryCount--) { int left1, right1, left2, right2; cin >> left1 >> right1 >> left2 >> right2; if (calculateHash (left1, right1) == calculateHash (left2, right2)) { cout << "Yes" << endl; } else { cout << "No" << endl; } } return 0 ; }
搜索与图论 包括DFS,BFS,树与图的深度优先遍历,树与图的广度优先遍历,拓扑排序,Dijkstra,bellman-ford,spfa,Floyd,Prim,Kruskal,染色法判定二分图,匈牙利算法等内容。
842. 排列数字 原题链接:https://www.acwing.com/problem/content/844/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 #include <iostream> using namespace std;const int N = 10 ;int path[N];int state[N];int n;void dfs (int u) { if (u > n) { for (int i = 1 ; i <= n; i++) cout << path[i] << " " ; cout << endl; } for (int i = 1 ; i <= n; i++) { if (!state[i]) { path[u] = i; state[i] = 1 ; dfs (u + 1 ); state[i] = 0 ; } } } int main () { cin >> n; dfs (1 ); }
843. n-皇后问题 原题链接:https://www.acwing.com/problem/content/845/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 #include <iostream> using namespace std;const int N = 20 ;int n;char g[N][N];bool row[N], col[N], dg[N], udg[N]; void dfs (int x, int y, int s) { if (y == n) y = 0 , x ++ ; if (x == n) { if (s == n) { for (int i = 0 ; i < n; i ++ ) puts (g[i]); puts ("" ); } return ; } if (!row[x] && !col[y] && !dg[x + y] && !udg[x - y + n]) { g[x][y] = 'Q' ; row[x] = col[y] = dg[x + y] = udg[x - y + n] = true ; dfs (x, y + 1 , s + 1 ); row[x] = col[y] = dg[x + y] = udg[x - y + n] = false ; g[x][y] = '.' ; } dfs (x, y + 1 , s); } int main () { cin >> n; for (int i = 0 ; i < n; i ++ ) for (int j = 0 ; j < n; j ++ ) g[i][j] = '.' ; dfs (0 , 0 , 0 ); return 0 ; }
845. 八数码 原题链接:https://www.acwing.com/problem/content/description/847/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 #include <iostream> #include <vector> #include <queue> #include <unordered_map> #include <algorithm> #include <cstring> using namespace std;int bfs (string start) { queue<string> q; unordered_map<string, int > dict; string goal = "12345678x" ; int dx[4 ] = {0 , 0 , 1 , -1 }; int dy[4 ] = {1 , -1 , 0 , 0 }; q.push (start); dict[start] = 0 ; while (q.size ()) { auto t = q.front (); q.pop (); int distance = dict[t]; if (t == goal) { return distance; } int pos = t.find ('x' ); int x = pos / 3 ; int y = pos % 3 ; for (int i = 0 ; i < 4 ; i++) { int xi = x + dx[i]; int yi = y + dy[i]; if (xi >= 0 && xi < 3 && yi >= 0 && yi < 3 ) { int posi = xi * 3 + yi; swap (t[pos], t[posi]); if (dict[t] == 0 ) { dict[t] = distance + 1 ; q.push (t); } swap (t[pos], t[posi]); } } } return -1 ; } int main () { string c, start; for (int i = 0 ; i < 9 ; i++) { cin >> c; start += c; } cout << bfs (start) << endl; return 0 ; }
846. 树的重心 原题链接:https://www.acwing.com/problem/content/848/
这题就是遍历一棵树的以各个点为根的子树的大小,找到其中最小
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 #include <iostream> #include <vector> using namespace std;const int MAX_NODES = 1e5 + 10 ; int num_nodes; vector<int > adjacency_list[MAX_NODES]; int subtree_sizes[MAX_NODES]; bool visited[MAX_NODES]; int centroid = MAX_NODES, max_subtree_size = MAX_NODES; void dfs (int node) { visited[node] = true ; subtree_sizes[node] = 1 ; int max_subtree = 0 ; for (int neighbor : adjacency_list[node]) { if (!visited[neighbor]) { dfs (neighbor); subtree_sizes[node] += subtree_sizes[neighbor]; max_subtree = max (max_subtree, subtree_sizes[neighbor]); } } max_subtree = max (max_subtree, num_nodes - subtree_sizes[node]); if (max_subtree < max_subtree_size) { max_subtree_size = max_subtree; centroid = node; } } int main () { cin >> num_nodes; for (int i = 1 ; i < num_nodes; i++) { int node_a, node_b; cin >> node_a >> node_b; adjacency_list[node_a].push_back (node_b); adjacency_list[node_b].push_back (node_a); } dfs (1 ); cout << max_subtree_size << endl; return 0 ; }
847. 图中点的层次 原题链接:https://www.acwing.com/problem/content/849/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 #include <iostream> #include <vector> #include <queue> #include <cstring> using std::vector;using std::queue;using std::cin;using std::cout;using std::endl;const int MAXN = 100005 ;vector<int > graph[MAXN]; bool visited[MAXN]; int distance[MAXN]; int bfs (int start, int end) { memset (visited, false , sizeof (visited)); memset (distance, -1 , sizeof (distance)); queue<int > q; visited[start] = true ; distance[start] = 0 ; q.push (start); while (!q.empty ()) { int node = q.front (); q.pop (); for (int neighbor : graph[node]) { if (!visited[neighbor]) { visited[neighbor] = true ; distance[neighbor] = distance[node] + 1 ; q.push (neighbor); } } } return distance[end]; } int main () { int n, m; cin >> n >> m; for (int i = 0 ; i < m; ++i) { int a, b; cin >> a >> b; graph[a].push_back (b); } int shortest_distance = bfs (1 , n); cout << shortest_distance << endl; return 0 ; }
848. 有向图的拓扑序列 原题链接:https://www.acwing.com/problem/content/description/850/
拓扑排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 #include <iostream> #include <vector> #include <stack> #include <cstring> using namespace std;const int MAXN = 100005 ;vector<int > graph[MAXN]; bool visited[MAXN]; bool on_stack[MAXN]; stack<int > topo_order; bool dfs (int node) { visited[node] = true ; on_stack[node] = true ; for (int neighbor : graph[node]) { if (!visited[neighbor]) { if (dfs (neighbor)) return true ; } else if (on_stack[neighbor]) { return true ; } } on_stack[node] = false ; topo_order.push (node); return false ; } int main () { int n, m; cin >> n >> m; for (int i = 0 ; i < m; ++i) { int x, y; cin >> x >> y; graph[x].push_back (y); } memset (visited, false , sizeof (visited)); memset (on_stack, false , sizeof (on_stack)); for (int i = 1 ; i <= n; ++i) { if (!visited[i]) { if (dfs (i)) { cout << -1 << endl; return 0 ; } } } while (!topo_order.empty ()) { cout << topo_order.top () << " " ; topo_order.pop (); } cout << endl; return 0 ; }
849. Dijkstra求最短路 I || 850. Dijkstra求最短路 II 原题链接:https://www.acwing.com/problem/content/851/ https://www.acwing.com/problem/content/852/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 #include <iostream> #include <vector> #include <queue> #include <limits> using namespace std;typedef pair<int , int > pii; const int INF = numeric_limits<int >::max (); int dijkstra (const vector<vector<pii>>& graph, int n, int start, int end) { vector<int > dist (n + 1 , INF) ; dist[start] = 0 ; priority_queue<pii, vector<pii>, greater<pii>> pq; pq.push ({0 , start}); while (!pq.empty ()) { int d = pq.top ().first; int node = pq.top ().second; pq.pop (); if (d > dist[node]) continue ; for (auto & edge : graph[node]) { int neighbor = edge.first; int weight = edge.second; if (dist[node] + weight < dist[neighbor]) { dist[neighbor] = dist[node] + weight; pq.push ({dist[neighbor], neighbor}); } } } if (dist[end] == INF) { return -1 ; } else { return dist[end]; } } int main () { int n, m; cin >> n >> m; vector<vector<pii>> graph (n + 1 ); for (int i = 0 ; i < m; ++i) { int x, y, z; cin >> x >> y >> z; graph[x].push_back ({y, z}); } int shortest_distance = dijkstra (graph, n, 1 , n); cout << shortest_distance << endl; return 0 ; }
853. 有边数限制的最短路 原题链接:https://www.acwing.com/problem/content/855/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 #include <iostream> #include <vector> #include <climits> using namespace std;struct Edge { int from, to, weight; Edge (int _from, int _to, int _weight) : from (_from), to (_to), weight (_weight) {} }; const int INF = INT_MAX; int main () { int n, m, k; cin >> n >> m >> k; vector<Edge> edges; for (int i = 0 ; i < m; ++i) { int x, y, z; cin >> x >> y >> z; edges.push_back (Edge (x, y, z)); } vector<int > dist (n + 1 , INF) ; dist[1 ] = 0 ; for (int i = 0 ; i < k; ++i) { vector<int > temp = dist; for (const auto & edge : edges) { if (dist[edge.from] != INF && dist[edge.from] + edge.weight < temp[edge.to]) { temp[edge.to] = dist[edge.from] + edge.weight; } } dist = temp; } if (dist[n] == INF) { cout << "impossible" << endl; } else { cout << dist[n] << endl; } return 0 ; }