├── Week12 ├── Rumpelstitskin │ ├── cx_description │ │ ├── english.md │ │ └── conf.yml │ └── src │ │ └── algorithm.cpp ├── PiedPiper │ └── src │ │ └── algorithm.cpp ├── NewYork │ └── src │ │ └── algorithm.cpp ├── ReturnOfTheJedi │ └── src │ │ └── algorithm.cpp └── WorldCup │ └── src │ └── algorithm.cpp ├── PreviousYears └── 2022 │ ├── AsterixInSwitzerland │ ├── cx_description │ │ ├── english.md │ │ └── conf.yml │ └── src │ │ └── algorithm.cpp │ ├── NewTiles │ └── src │ │ └── algorithm.cpp │ ├── CeryneianHind │ └── src │ │ └── algorithm.cpp │ ├── SearchSnippets │ └── src │ │ └── algorithm.cpp │ ├── ShoppingTrip │ └── src │ │ └── algorithm.cpp │ ├── TheNemeanLion │ └── src │ │ └── algorithm.cpp │ ├── Evolution │ └── src │ │ └── algorithm.cpp │ ├── Tracking │ └── src │ │ └── algorithm.cpp │ ├── EmpireStrikesBack │ └── src │ │ └── algorithm.cpp │ ├── FleetRace │ └── src │ │ └── algorithm.cpp │ ├── LightTheStage │ └── src │ │ └── algorithm.cpp │ ├── RevengeOfTheSith │ └── src │ │ └── algorithm.cpp │ ├── Marathon │ └── src │ │ └── algorithm.cpp │ ├── LudoBagman │ └── src │ │ └── algorithm.cpp │ ├── CarSharing │ └── src │ │ └── algorithm.cpp │ └── TheHandTourney │ └── src │ └── algorithm.cpp ├── .gitignore ├── CppIntroduction ├── BFS │ ├── cx_description │ │ ├── conf.yml │ │ └── english.md │ └── src │ │ └── algorithm.cpp ├── DFS │ ├── cx_description │ │ ├── conf.yml │ │ └── english.md │ └── src │ │ └── algorithm.cpp ├── Maps │ ├── cx_description │ │ ├── conf.yml │ │ └── english.md │ └── src │ │ └── algorithm.cpp ├── Sets │ ├── cx_description │ │ ├── conf.yml │ │ └── english.md │ └── src │ │ └── algorithm.cpp ├── Sort │ ├── cx_description │ │ ├── conf.yml │ │ └── english.md │ └── src │ │ └── algorithm.cpp ├── SumIt │ ├── cx_description │ │ ├── conf.yml │ │ └── english.md │ └── src │ │ └── algorithm.cpp ├── HelloWorld │ ├── cx_description │ │ ├── conf.yml │ │ └── english.md │ └── src │ │ └── algorithm.cpp ├── Strings │ ├── cx_description │ │ ├── conf.yml │ │ └── english.md │ └── src │ │ └── algorithm.cpp ├── Vectors │ ├── cx_description │ │ ├── conf.yml │ │ └── english.md │ └── src │ │ └── algorithm.cpp └── BasicDataTypes │ ├── cx_description │ ├── conf.yml │ └── english.md │ └── src │ └── algorithm.cpp ├── Exam ├── P1 │ ├── Croquet │ │ └── src │ │ │ └── algorithm.cpp │ └── QueenOfHearts │ │ └── src │ │ └── algorithm.cpp └── P2 │ ├── RabbitClan │ └── src │ │ └── algorithm.cpp │ └── MadTeaParty │ └── src │ └── algorithm.cpp ├── Week13 ├── FightingPitsOfMeeren │ └── src │ │ └── algorithm.cpp ├── DHL │ └── src │ │ └── algorithm.cpp ├── AugeanStables │ └── src │ │ └── algorithm.cpp ├── CasinoRoyale │ └── src │ │ └── algorithm.cpp └── Schneewittchen │ └── src │ └── algorithm.cpp ├── Week01 ├── BuildTheSum │ └── src │ │ └── algorithm.cpp ├── Dominoes │ └── src │ │ └── algorithm.cpp ├── EvenPairs │ └── src │ │ └── algorithm.cpp └── EvenMatrices │ └── src │ └── algorithm.cpp ├── Week05 ├── Boats │ └── src │ │ └── algorithm.cpp ├── MovingBooks │ └── src │ │ └── algorithm.cpp ├── PlanetExpress │ └── src │ │ └── algorithm.cpp ├── SeverusSnape │ └── src │ │ └── algorithm.cpp └── AsterixTheGaul │ └── src │ └── algorithm.cpp ├── Week02 ├── DeckOfCards │ └── src │ │ └── algorithm.cpp ├── BurningCoins │ └── src │ │ └── algorithm.cpp ├── TheGreatGame │ └── src │ │ └── algorithm.cpp ├── BeachBars │ └── src │ │ └── algorithm.cpp └── LordVoldemort │ └── src │ └── algorithm.cpp ├── Week04 ├── Hit │ └── src │ │ └── algorithm.cpp ├── Antenna │ └── src │ │ └── algorithm.cpp ├── FirstHit │ └── src │ │ └── algorithm.cpp ├── IronIslands │ └── src │ │ └── algorithm.cpp └── HikingMaps │ └── src │ └── algorithm.cpp ├── Week07 ├── Bistro │ └── src │ │ └── algorithm.cpp ├── Octopussy │ └── src │ │ └── algorithm.cpp ├── Germs │ └── src │ │ └── algorithm.cpp ├── H1N1 │ └── src │ │ └── algorithm.cpp └── GoldenEye │ └── src │ └── algorithm.cpp ├── Week03 ├── JamesBondSovereigns │ └── src │ │ └── algorithm.cpp ├── ImportantBridges │ └── src │ │ └── algorithm.cpp ├── FirstStepsBGL │ └── src │ │ └── algorithm.cpp ├── BuddySelection │ └── src │ │ └── algorithm.cpp └── AntChallenge │ └── src │ └── algorithm.cpp ├── Week11 ├── Legions │ └── src │ │ └── algorithm.cpp ├── AsterixChariotRace │ └── src │ │ └── algorithm.cpp ├── PhantomMenace │ └── src │ │ └── algorithm.cpp ├── India │ └── src │ │ └── algorithm.cpp └── DeanThomas │ └── src │ └── algorithm.cpp ├── Week08 ├── Diet │ └── src │ │ └── algorithm.cpp ├── Inball │ └── src │ │ └── algorithm.cpp ├── WhatIsTheMaximum │ └── src │ │ └── algorithm.cpp ├── Suez │ └── src │ │ └── algorithm.cpp └── KingdomDefence │ └── src │ └── algorithm.cpp ├── Week06 ├── Motorcycles │ └── src │ │ └── algorithm.cpp ├── Knights │ └── src │ │ └── algorithm.cpp ├── Tiles │ └── src │ │ └── algorithm.cpp ├── CoinTossingTournament │ └── src │ │ └── algorithm.cpp └── London │ └── src │ └── algorithm.cpp ├── Week09 ├── Algocoon │ └── src │ │ └── algorithm.cpp ├── Canteen │ └── src │ │ └── algorithm.cpp ├── RealEstateMarket │ └── src │ │ └── algorithm.cpp ├── Idefix │ └── src │ │ └── algorithm.cpp └── PlacingKnights │ └── src │ └── algorithm.cpp ├── Week10 ├── SanFrancisco │ └── src │ │ └── algorithm.cpp ├── SurveillancePhotograph │ └── src │ │ └── algorithm.cpp ├── Lannister │ └── src │ │ └── algorithm.cpp ├── RubeusHagrid │ └── src │ │ └── algorithm.cpp └── Clues │ └── src │ └── algorithm.cpp ├── Week14 └── OnHerMajestySecretService │ └── src │ └── algorithm.cpp └── README.md /Week12/Rumpelstitskin/cx_description/english.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /PreviousYears/2022/AsterixInSwitzerland/cx_description/english.md: -------------------------------------------------------------------------------- 1 | # Some Description 2 | 3 | Test -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode/ 2 | build/ 3 | .algolabVS 4 | .cx_metadata.json 5 | CMakeLists.txt 6 | debug_test_data.txt -------------------------------------------------------------------------------- /CppIntroduction/BFS/cx_description/conf.yml: -------------------------------------------------------------------------------- 1 | descriptions: 2 | english: 3 | name: English 4 | default: true 5 | -------------------------------------------------------------------------------- /CppIntroduction/DFS/cx_description/conf.yml: -------------------------------------------------------------------------------- 1 | descriptions: 2 | english: 3 | name: English 4 | default: true 5 | -------------------------------------------------------------------------------- /CppIntroduction/Maps/cx_description/conf.yml: -------------------------------------------------------------------------------- 1 | descriptions: 2 | english: 3 | name: English 4 | default: true 5 | -------------------------------------------------------------------------------- /CppIntroduction/Sets/cx_description/conf.yml: -------------------------------------------------------------------------------- 1 | descriptions: 2 | english: 3 | name: English 4 | default: true 5 | -------------------------------------------------------------------------------- /CppIntroduction/Sort/cx_description/conf.yml: -------------------------------------------------------------------------------- 1 | descriptions: 2 | english: 3 | name: English 4 | default: true 5 | -------------------------------------------------------------------------------- /CppIntroduction/SumIt/cx_description/conf.yml: -------------------------------------------------------------------------------- 1 | descriptions: 2 | english: 3 | name: English 4 | default: true 5 | -------------------------------------------------------------------------------- /Week12/Rumpelstitskin/cx_description/conf.yml: -------------------------------------------------------------------------------- 1 | descriptions: 2 | english: 3 | name: English 4 | default: true 5 | -------------------------------------------------------------------------------- /CppIntroduction/HelloWorld/cx_description/conf.yml: -------------------------------------------------------------------------------- 1 | descriptions: 2 | english: 3 | name: English 4 | default: true 5 | -------------------------------------------------------------------------------- /CppIntroduction/Strings/cx_description/conf.yml: -------------------------------------------------------------------------------- 1 | descriptions: 2 | english: 3 | name: English 4 | default: true 5 | -------------------------------------------------------------------------------- /CppIntroduction/Vectors/cx_description/conf.yml: -------------------------------------------------------------------------------- 1 | descriptions: 2 | english: 3 | name: English 4 | default: true 5 | -------------------------------------------------------------------------------- /CppIntroduction/BasicDataTypes/cx_description/conf.yml: -------------------------------------------------------------------------------- 1 | descriptions: 2 | english: 3 | name: English 4 | default: true 5 | -------------------------------------------------------------------------------- /PreviousYears/2022/AsterixInSwitzerland/cx_description/conf.yml: -------------------------------------------------------------------------------- 1 | descriptions: 2 | english: 3 | name: English 4 | default: true 5 | # Optionally add mulitple versions here. 6 | # Use the file name without the .md extension as key and add a `name:` to it. 7 | # For example, add 8 | # german: 9 | # name: Deutsch -------------------------------------------------------------------------------- /CppIntroduction/HelloWorld/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | int main() { 10 | std::ios_base::sync_with_stdio(false); 11 | 12 | std::cout << "Hello World!" << std::endl; 13 | } 14 | -------------------------------------------------------------------------------- /CppIntroduction/HelloWorld/cx_description/english.md: -------------------------------------------------------------------------------- 1 | # Hello world 2 | 3 | Welcome to C`++`! In this exercise you are supposed to write 4 | '`Hello World!`' to the standard output. 5 | 6 | ## Input 7 | 8 | No input is needed for this exercise. 9 | 10 | ## Output 11 | 12 | Output a single line containing '`Hello World!`'. 13 | 14 | ## Points 15 | 16 | This exercise is worth $100$ points in total. -------------------------------------------------------------------------------- /Exam/P1/Croquet/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | void testcase() { 10 | // TODO: 11 | return; 12 | } 13 | 14 | int main() { 15 | std::ios_base::sync_with_stdio(false); 16 | 17 | int t; 18 | std::cin >> t; 19 | for (int i = 0; i < t; ++i) 20 | testcase(); 21 | } 22 | -------------------------------------------------------------------------------- /Exam/P1/QueenOfHearts/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | void testcase() { 10 | // TODO: 11 | return; 12 | } 13 | 14 | int main() { 15 | std::ios_base::sync_with_stdio(false); 16 | 17 | int t; 18 | std::cin >> t; 19 | for (int i = 0; i < t; ++i) 20 | testcase(); 21 | } 22 | -------------------------------------------------------------------------------- /PreviousYears/2022/NewTiles/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | void testcase() { 10 | // TODO: 11 | return; 12 | } 13 | 14 | int main() { 15 | std::ios_base::sync_with_stdio(false); 16 | 17 | int t; 18 | std::cin >> t; 19 | for (int i = 0; i < t; ++i) 20 | testcase(); 21 | } 22 | -------------------------------------------------------------------------------- /Week13/FightingPitsOfMeeren/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | void testcase() { 10 | // TODO: 11 | return; 12 | } 13 | 14 | int main() { 15 | std::ios_base::sync_with_stdio(false); 16 | 17 | int t; 18 | std::cin >> t; 19 | for (int i = 0; i < t; ++i) 20 | testcase(); 21 | } 22 | -------------------------------------------------------------------------------- /PreviousYears/2022/CeryneianHind/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | void testcase() { 10 | // TODO: 11 | return; 12 | } 13 | 14 | int main() { 15 | std::ios_base::sync_with_stdio(false); 16 | 17 | int t; 18 | std::cin >> t; 19 | for (int i = 0; i < t; ++i) 20 | testcase(); 21 | } 22 | -------------------------------------------------------------------------------- /PreviousYears/2022/SearchSnippets/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | void testcase() { 10 | // TODO: 11 | return; 12 | } 13 | 14 | int main() { 15 | std::ios_base::sync_with_stdio(false); 16 | 17 | int t; 18 | std::cin >> t; 19 | for (int i = 0; i < t; ++i) 20 | testcase(); 21 | } 22 | -------------------------------------------------------------------------------- /PreviousYears/2022/ShoppingTrip/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | void testcase() { 10 | // TODO: 11 | return; 12 | } 13 | 14 | int main() { 15 | std::ios_base::sync_with_stdio(false); 16 | 17 | int t; 18 | std::cin >> t; 19 | for (int i = 0; i < t; ++i) 20 | testcase(); 21 | } 22 | -------------------------------------------------------------------------------- /PreviousYears/2022/TheNemeanLion/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | void testcase() { 10 | // TODO: 11 | return; 12 | } 13 | 14 | int main() { 15 | std::ios_base::sync_with_stdio(false); 16 | 17 | int t; 18 | std::cin >> t; 19 | for (int i = 0; i < t; ++i) 20 | testcase(); 21 | } 22 | -------------------------------------------------------------------------------- /CppIntroduction/SumIt/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | void testcase() { 10 | int n; std::cin >> n; 11 | int sum = 0; 12 | 13 | while (n--) { 14 | int x; std::cin >> x; 15 | sum += x; 16 | } 17 | 18 | std::cout << sum << std::endl; 19 | } 20 | 21 | int main() { 22 | std::ios_base::sync_with_stdio(false); 23 | 24 | int t; 25 | std::cin >> t; 26 | for (int i = 0; i < t; ++i) 27 | testcase(); 28 | } 29 | -------------------------------------------------------------------------------- /Week01/BuildTheSum/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | void testcase() { 10 | int n; std::cin >> n; 11 | int sum = 0; 12 | 13 | while (n--) { 14 | int x; std::cin >> x; 15 | sum += x; 16 | } 17 | 18 | std::cout << sum << std::endl; 19 | } 20 | 21 | int main() { 22 | std::ios_base::sync_with_stdio(false); 23 | 24 | int t; 25 | std::cin >> t; 26 | for (int i = 0; i < t; ++i) 27 | testcase(); 28 | } 29 | -------------------------------------------------------------------------------- /CppIntroduction/BasicDataTypes/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | void testcase() { 10 | int i; 11 | long l; 12 | std::string s; 13 | double d; 14 | 15 | std::cin >> i >> l >> s >> d; 16 | std::cout << std::setprecision(2) 17 | << i << " " 18 | << l << " " 19 | << s << " " 20 | << std::fixed << d << std::endl; 21 | } 22 | 23 | int main() { 24 | std::ios_base::sync_with_stdio(false); 25 | 26 | int t; 27 | std::cin >> t; 28 | for (int i = 0; i < t; ++i) 29 | testcase(); 30 | } 31 | -------------------------------------------------------------------------------- /Week01/Dominoes/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | void testcase() { 10 | int n; std::cin >> n; 11 | int covered = 1; 12 | std::vector d(n, 0); 13 | 14 | for (int i = 0; i < n; i++) { 15 | int h; std::cin >> h; 16 | 17 | if (covered > i) { 18 | covered = std::max(covered, i + h); 19 | } 20 | } 21 | 22 | std::cout << std::min(covered, n) << std::endl; 23 | } 24 | 25 | int main() { 26 | std::ios_base::sync_with_stdio(false); 27 | 28 | int t; 29 | std::cin >> t; 30 | for (int i = 0; i < t; ++i) 31 | testcase(); 32 | } 33 | -------------------------------------------------------------------------------- /Week01/EvenPairs/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | void testcase() { 10 | int n; std::cin >> n; 11 | int even = 1, odd = 0, sum = 0; 12 | 13 | while (n--) { 14 | int a; std::cin >> a; 15 | sum += a; 16 | 17 | if (sum % 2) { 18 | odd++; 19 | } else { 20 | even++; 21 | } 22 | } 23 | 24 | std::cout << (even * (even - 1)) / 2 + (odd * (odd - 1)) / 2 << std::endl; 25 | } 26 | 27 | int main() { 28 | std::ios_base::sync_with_stdio(false); 29 | 30 | int t; 31 | std::cin >> t; 32 | for (int i = 0; i < t; ++i) 33 | testcase(); 34 | } 35 | -------------------------------------------------------------------------------- /CppIntroduction/Strings/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | void testcase() { 10 | std::string a, b; 11 | std::cin >> a >> b; 12 | 13 | std::string c = a, d = b; 14 | std::reverse(c.begin(), c.end()); 15 | std::reverse(d.begin(), d.end()); 16 | 17 | char tmp = c[0]; 18 | c[0] = d[0]; 19 | d[0] = tmp; 20 | 21 | std::cout << a.length() << " " << b.length() << std::endl; 22 | std::cout << a + b << std::endl; 23 | std::cout << c << " " << d << std::endl; 24 | } 25 | 26 | int main() { 27 | std::ios_base::sync_with_stdio(false); 28 | 29 | int t; 30 | std::cin >> t; 31 | for (int i = 0; i < t; ++i) 32 | testcase(); 33 | } 34 | -------------------------------------------------------------------------------- /CppIntroduction/Vectors/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | void testcase() { 10 | int n; std::cin >> n; 11 | std::vector v(n); 12 | 13 | for (int i = 0; i < n; ++i) 14 | std::cin >> v[i]; 15 | 16 | int d; std::cin >> d; 17 | v.erase(v.begin() + d); 18 | 19 | int a, b; std::cin >> a >> b; 20 | v.erase(v.begin() + a, v.begin() + b + 1); 21 | 22 | for (int i: v) 23 | std::cout << i << " "; 24 | 25 | if (v.size() == 0) 26 | std::cout << "Empty"; 27 | 28 | std::cout << std::endl; 29 | } 30 | 31 | int main() { 32 | std::ios_base::sync_with_stdio(false); 33 | 34 | int t; 35 | std::cin >> t; 36 | for (int i = 0; i < t; ++i) 37 | testcase(); 38 | } 39 | -------------------------------------------------------------------------------- /CppIntroduction/Sets/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | void testcase() { 11 | std::set s = {}; 12 | int q; std::cin >> q; 13 | 14 | while (q--) { 15 | int a, b; std::cin >> a >> b; 16 | 17 | if (a) { 18 | auto rm = s.find(b); 19 | if (rm != s.end()) 20 | s.erase(rm); 21 | } else 22 | s.insert(b); 23 | } 24 | 25 | for (int i: s) 26 | std::cout << i << " "; 27 | 28 | if (s.empty()) 29 | std::cout << "Empty"; 30 | 31 | std::cout << std::endl; 32 | } 33 | 34 | int main() { 35 | std::ios_base::sync_with_stdio(false); 36 | 37 | int t; 38 | std::cin >> t; 39 | for (int i = 0; i < t; ++i) 40 | testcase(); 41 | } 42 | -------------------------------------------------------------------------------- /CppIntroduction/Sort/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | void testcase() { 10 | int n; std::cin >> n; 11 | std::vector v(n); 12 | 13 | for (int i = 0; i < n; i++) 14 | std::cin >> v[i]; 15 | 16 | std::random_shuffle(v.begin(), v.end()); 17 | 18 | int x; std::cin >> x; 19 | if (x) { 20 | std::sort(v.begin(), v.end(), std::greater()); 21 | } else { 22 | std::sort(v.begin(), v.end()); 23 | } 24 | 25 | for (const auto n: v) 26 | std::cout << n << " "; 27 | std::cout << std::endl; 28 | } 29 | 30 | int main() { 31 | std::ios_base::sync_with_stdio(false); 32 | 33 | int t; 34 | std::cin >> t; 35 | for (int i = 0; i < t; ++i) 36 | testcase(); 37 | } 38 | -------------------------------------------------------------------------------- /CppIntroduction/SumIt/cx_description/english.md: -------------------------------------------------------------------------------- 1 | # Build the Sum 2 | 3 | Given $n \geq 1$ integers $a_0, a_1, \ldots, a_{n - 1}$, calculate the 4 | sum $\sum_{i = 0}^{n - 1} a_i$. 5 | 6 | ## Input 7 | 8 | The first line of the input contains the number $t \leq 10$ of test 9 | cases. Each of the $t$ test cases is described as follows. 10 | 11 | - It starts with a line that contains an integer $n$, denoting the 12 | number of integers to sum up, such that $0 \leq n \leq 10$. 13 | 14 | - The following line contains $n$ integers $\verb|a|_0\ \ldots\ 15 | \verb|a|_{n - 1}$, separated by a space, such that 16 | $-1000 \leq a_i \leq 17 | 1000$, for every $i \in \{0, \ldots, n - 1\}$. 18 | 19 | ## Output 20 | 21 | For each test case output one line with a single integer that denotes 22 | the required sum. 23 | 24 | ## Points 25 | 26 | There is one group of test sets, worth $100$ points in total. -------------------------------------------------------------------------------- /Week05/Boats/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | void testcase() { 10 | int n; std::cin >> n; 11 | std::vector> b(n); 12 | 13 | for (int i = 0; i < n; i++) { 14 | int l, p; std::cin >> l >> p; 15 | b[i] = std::make_pair(p, l); 16 | } 17 | 18 | std::sort(b.begin(), b.end()); 19 | 20 | int count = 1; 21 | for (int i = 1, p = b[0].first; i < n;) { 22 | int next = b[n - 1].first + b[n - 1].second; 23 | for (; i < n && next > b[i].first; i++) 24 | next = std::min(next, std::max(p + b[i].second, b[i].first)); 25 | 26 | p = next; 27 | count++; 28 | } 29 | 30 | std::cout << count << std::endl; 31 | } 32 | 33 | int main() { 34 | std::ios_base::sync_with_stdio(false); 35 | 36 | int t; 37 | std::cin >> t; 38 | for (int i = 0; i < t; ++i) 39 | testcase(); 40 | } 41 | -------------------------------------------------------------------------------- /CppIntroduction/BasicDataTypes/cx_description/english.md: -------------------------------------------------------------------------------- 1 | # Basic Data Types 2 | 3 | In this exercise you have to read several basic C`++` data types and 4 | output them to the standard output in the required format. 5 | 6 | ## Input 7 | 8 | The first line of the input contains the number $t \leq 10$ of test 9 | cases. Each of the $t$ test cases is described as follows. 10 | 11 | - It consists of four values, separated by a space. These values have 12 | different types, as given by the following order: `int`, `long`, 13 | `std::string`, `double`. 14 | 15 | *Note:* You might want to use `long long` instead of `long` to store 16 | large integers depending on your machine. 17 | 18 | ## Output 19 | 20 | For each test case output one line containing all input data types, 21 | separated by a space. Floating point numbers should be rounded up to $2$ 22 | decimal digits. 23 | 24 | ## Points 25 | 26 | There is one group of test sets, worth $100$ points in total. -------------------------------------------------------------------------------- /CppIntroduction/Sets/cx_description/english.md: -------------------------------------------------------------------------------- 1 | # Sets 2 | In this exercise you are supposed to do some operations with sets. 3 | 4 | ## Input 5 | 6 | The first line of the input contains the number $t \leq 10$ of test 7 | cases. Each of the $t$ test cases is described as follows. 8 | 9 | - It starts with a line that contains an integer `q`, such that $0 10 | \leq q \leq 10$. 11 | 12 | - The following $q$ lines each contain two integers `a b`, separated 13 | by a space, such that $a \in \{0, 1\}$ and $-1000 \leq b \leq 14 | 1000$, in one of the following forms: 15 | 16 | - `0 b`: add the element $b$ to the set; 17 | 18 | - `1 b`: delete the element $b$ from the set. 19 | 20 | ## Output 21 | 22 | For each test set output one line with the remaining elements of the set 23 | separated by a space. If there are no elements remaining in the set 24 | output '`Empty`'. 25 | 26 | ## Points 27 | 28 | There is one group of test sets, worth $100$ points in total. -------------------------------------------------------------------------------- /Week02/DeckOfCards/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | void testcase() { 10 | int n, k; std::cin >> n >> k; 11 | std::vector v(n + 1, 0); 12 | 13 | for (int i = 1; i <= n; i++) { 14 | int a; std::cin >> a; 15 | v[i] = v[i - 1] + a; 16 | } 17 | 18 | int i = 1, j = 1, best_i = 0, best_j = 0, best_err = std::numeric_limits::max(); 19 | while (j <= n) { 20 | int err = k - (v[j] - v[i - 1]); 21 | int abs_err = std::abs(err); 22 | 23 | if (abs_err < best_err) { 24 | best_i = i; 25 | best_j = j; 26 | best_err = abs_err; 27 | } 28 | 29 | if (err < 0 && i < j) { 30 | i++; 31 | } else { 32 | j++; 33 | } 34 | } 35 | 36 | std::cout << best_i - 1 << " " << best_j - 1 << std::endl; 37 | } 38 | 39 | int main() { 40 | std::ios_base::sync_with_stdio(false); 41 | 42 | int t; 43 | std::cin >> t; 44 | for (int i = 0; i < t; ++i) 45 | testcase(); 46 | } 47 | -------------------------------------------------------------------------------- /Week13/DHL/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | int n; 10 | std::vector a, b; 11 | std::vector> dp; 12 | 13 | void testcase() { 14 | std::cin >> n; 15 | a = std::vector (n); 16 | b = std::vector (n); 17 | dp = std::vector> (n + 1, std::vector(n + 1, 100*1000)); 18 | 19 | for (int i = 0; i < n; i++) 20 | std::cin >> a[i]; 21 | 22 | for (int i = 0; i < n; i++) 23 | std::cin >> b[i]; 24 | 25 | dp[0][0] = 0; 26 | for (int i = 1; i <= n; i++) { 27 | for (int j = 1; j <= n; j++) { 28 | dp[i][j] = (a[i - 1] - 1) * (b[j - 1] - 1) + std::min(dp[i - 1][j], std::min(dp[i][j - 1], dp[i - 1][j - 1])); 29 | } 30 | } 31 | 32 | std::cout << dp[n][n] << std::endl; 33 | } 34 | 35 | int main() { 36 | std::ios_base::sync_with_stdio(false); 37 | 38 | int t; 39 | std::cin >> t; 40 | for (int i = 0; i < t; ++i) 41 | testcase(); 42 | } 43 | -------------------------------------------------------------------------------- /CppIntroduction/BFS/cx_description/english.md: -------------------------------------------------------------------------------- 1 | # BFS 2 | Compute the distances of all vertices from a given starting vertex using 3 | BFS. 4 | 5 | ## Input 6 | 7 | The first line of the input contains the number $t \leq 10$ of test 8 | cases. Each of the $t$ test cases is described as follows. 9 | 10 | - It starts with a line that contains three integers `n m v`, 11 | separated by a space, denoting the number of vertices, the number of 12 | edges, and the starting vertex, and such that $0 \leq n \leq 10^3$, 13 | $0 14 | \leq m \leq \binom{n}{2}$, and $0 \leq v \leq n - 1$. 15 | 16 | - The following $m$ lines each contain two integers `a b`, separated 17 | by a space, indicating that $\{a, b\}$ is an edge of the graph. 18 | 19 | ## Output 20 | 21 | For each test case you should output one line containing the distance of 22 | the vertices from $v$, ordered by increasing labels. If a vertex cannot 23 | be reached, its distance is $-1$. 24 | 25 | ## Points 26 | 27 | There is one group of test sets, worth $100$ points in total. -------------------------------------------------------------------------------- /CppIntroduction/Strings/cx_description/english.md: -------------------------------------------------------------------------------- 1 | # Strings 2 | 3 | In this exercise you practise some operations on strings. 4 | 5 | ## Input 6 | 7 | The first line of the input contains the number $t \leq 10$ of test 8 | cases. Each of the $t$ test cases is described as follows. 9 | 10 | - It consists of a line that contains two strings `a b`, separated by 11 | a space, and such that their individual length is at most $10$. 12 | 13 | ## Output 14 | 15 | For each test case output three lines. 16 | 17 | - The first line contains two integers, separated by a space, 18 | representing the length of $a$ and $b$, respectively. 19 | 20 | - The second line contains a string obtained by concatenating the 21 | given strings $a$ and $b$. 22 | 23 | - The third line contains two strings `c` and `d`, where $c$ and $d$ 24 | are obtained by first reversing the strings $a$ and $b$ and then 25 | swapping the first characters of the newly obtained strings. 26 | 27 | ## Points 28 | 29 | There is one group of test sets, worth $100$ points in total. -------------------------------------------------------------------------------- /Week04/Hit/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | using K = CGAL::Exact_predicates_inexact_constructions_kernel; 12 | 13 | void testcase(long n) { 14 | long x, y, a, b; std::cin >> x >> y >> a >> b; 15 | K::Point_2 p1(x, y), p2(a, b); 16 | K::Ray_2 ray(p1, p2); 17 | 18 | for (int i = 0; i < n; i++) { 19 | long r, s, t, u; std::cin >> r >> s >> t >> u; 20 | K::Point_2 start(r, s), end(t, u); 21 | K::Segment_2 segment(start, end); 22 | 23 | if (CGAL::do_intersect(ray, segment)) { 24 | for (; i < n - 1; i++) 25 | std::cin >> r >> s >> t >> u; 26 | 27 | std::cout << "yes" << std::endl; 28 | return; 29 | } 30 | } 31 | std::cout << "no" << std::endl; 32 | } 33 | 34 | int main() { 35 | std::ios_base::sync_with_stdio(false); 36 | 37 | long n; std::cin >> n; 38 | while (n) { 39 | testcase(n); 40 | std::cin >> n; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /CppIntroduction/Maps/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | void testcase() { 12 | std::map> m = {}; 13 | int q; std::cin >> q; 14 | 15 | while (q--) { 16 | unsigned int a; std::cin >> a; 17 | std::string b; std::cin >> b; 18 | 19 | if (a) { 20 | auto s = m.find(b); 21 | 22 | if (s != m.end()) 23 | s->second.insert(a); 24 | else 25 | m.insert(std::make_pair(b, std::set({a}))); 26 | } else 27 | m.erase(b); 28 | } 29 | 30 | std::string s; std::cin >> s; 31 | auto tgt = m.find(s); 32 | 33 | if (tgt == m.end()) 34 | std::cout << "Empty"; 35 | else 36 | for (auto const& a: tgt->second) 37 | std::cout << a << " "; 38 | 39 | std::cout << std::endl; 40 | } 41 | 42 | int main() { 43 | std::ios_base::sync_with_stdio(false); 44 | 45 | int t; 46 | std::cin >> t; 47 | for (int i = 0; i < t; ++i) 48 | testcase(); 49 | } 50 | -------------------------------------------------------------------------------- /CppIntroduction/Sort/cx_description/english.md: -------------------------------------------------------------------------------- 1 | # Sort 2 | In this exercise you are supposed to do some sorting of integers. 3 | 4 | ## Input 5 | 6 | The first line of the input contains the number $t \leq 10$ of test 7 | cases. Each of the $t$ test cases is described as follows. 8 | 9 | - It starts with a line that contains an integer `n`, such that $0 10 | \leq n \leq 10^5$. 11 | 12 | - The following line contains $n$ integers $\verb|a|_0\ \ldots\ 13 | \verb|a|_{n - 1}$, separated by a space, such that 14 | $-1000 \leq a_i \leq 15 | 1000$, for all $i \in \{0, \ldots, n - 1\}$. 16 | 17 | - The following line contains an integer `x`, denoting whether the 18 | numbers should be sorted in a non-decreasing order or in a 19 | non-increasing order, and such that $x \in \{0, 1\}$. 20 | 21 | ## Output 22 | 23 | For each test case output one line with the numbers sorted in a 24 | non-decreasing order if $x = 0$, and in a non-increasing order 25 | otherwise. 26 | 27 | ## Points 28 | 29 | There is one group of test sets, worth $100$ points in total. -------------------------------------------------------------------------------- /Exam/P2/RabbitClan/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | typedef std::vector> vec2d; 10 | 11 | void testcase() { 12 | int n, m; std::cin >> n >> m; 13 | vec2d dp(n + 1, std::vector(m + 1, 0)), recsum(n + 1, std::vector(m + 1, 0)); 14 | 15 | for (int i = 1; i <= n; i++) { 16 | for (int j = 1; j <= m; j++) { 17 | long r; std::cin >> r; 18 | recsum[i][j] = r + recsum[i - 1][j] + recsum[i][j - 1] - recsum[i - 1][j - 1]; 19 | } 20 | } 21 | 22 | for (int i = n - 1; i >= 1; i--) { 23 | for (int j = m - 1; j >= 1; j--) { 24 | long east = dp[i][j + 1] + recsum[n][j] - recsum[i][j]; 25 | long south = dp[i + 1][j] + recsum[i][m] - recsum[i][j]; 26 | dp[i][j] = std::min(east, south); 27 | } 28 | } 29 | 30 | std::cout << dp[1][1] << std::endl; 31 | } 32 | 33 | int main() { 34 | std::ios_base::sync_with_stdio(false); 35 | 36 | int t; 37 | std::cin >> t; 38 | for (int i = 0; i < t; ++i) 39 | testcase(); 40 | } 41 | -------------------------------------------------------------------------------- /Week05/MovingBooks/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | void testcase() 10 | { 11 | int n, m; std::cin >> n >> m; 12 | std::vector s(n); 13 | std::vector w(m); 14 | std::vector x(n, 0); 15 | 16 | for (int i = 0; i < n; i++) 17 | std::cin >> s[i]; 18 | 19 | for (int i = 0; i < m; i++) 20 | std::cin >> w[i]; 21 | 22 | std::sort(s.begin(), s.end(), std::greater()); 23 | std::sort(w.begin(), w.end(), std::greater()); 24 | 25 | if (s[0] < w[0]) { 26 | std::cout << "impossible" << std::endl; 27 | return; 28 | } 29 | 30 | for (int i = 0, j = 0; i < m; i++) { 31 | while (j < n && s[j] >= w[i]) 32 | j++; 33 | 34 | (*std::lower_bound(x.begin(), x.begin() + j - 1, x[j - 1], std::greater()))++; 35 | } 36 | 37 | std::cout << (x[0] * 3 - 1) << std::endl; 38 | } 39 | 40 | int main() 41 | { 42 | std::ios_base::sync_with_stdio(false); 43 | 44 | int t; 45 | std::cin >> t; 46 | for (int i = 0; i < t; ++i) 47 | testcase(); 48 | } 49 | -------------------------------------------------------------------------------- /CppIntroduction/Maps/cx_description/english.md: -------------------------------------------------------------------------------- 1 | # Maps 2 | In this exercise you are supposed to do some operations with maps. 3 | 4 | ## Input 5 | 6 | The first line of the input contains the number $t \leq 10$ of test 7 | cases. Each of the $t$ test cases is described as follows. 8 | 9 | - It starts with a line that contains an integer `q`, such that $0 10 | \leq q \leq 10$. 11 | 12 | - The following $q$ lines each contain an integer and a string `a b`, 13 | separated by a space, such that $0 \leq a \leq 1000$ and $b$ is of 14 | length at most $10$, in one of the following forms: 15 | 16 | - `0 b`: erase all entries with $b$ as the key; 17 | 18 | - `x b`, for $x > 0$: add an entry with key $b$ and value $x$ to 19 | the map. 20 | 21 | - The following line contains a string $s$ consisting of length at 22 | most $10$. 23 | 24 | ## Output 25 | 26 | For each test case output all the values with the key $s$ in a 27 | non-decreasing order, separated by a space. If there are no elements 28 | with the key $s$ output '`Empty`'. 29 | 30 | ## Points 31 | 32 | There is one group of test sets, worth $100$ points in total. -------------------------------------------------------------------------------- /Week07/Bistro/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | using K = CGAL::Exact_predicates_inexact_constructions_kernel; 13 | using P = K::Point_2; 14 | using Triangulation = CGAL::Delaunay_triangulation_2; 15 | using Face_iterator = Triangulation::Finite_faces_iterator; 16 | 17 | void testcase(int n) { 18 | Triangulation t; 19 | 20 | for (int i = 0; i < n; i++) { 21 | int x, y; std::cin >> x >> y; 22 | t.insert(P(x, y)); 23 | } 24 | 25 | int m; std::cin >> m; 26 | std::cout << std::setprecision(0) << std::fixed; 27 | for (int i = 0; i < m; i++) { 28 | int x, y; std::cin >> x >> y; 29 | P p(x, y); 30 | 31 | auto v = t.nearest_vertex(p); 32 | std::cout << CGAL::squared_distance(p, v->point()) << std::endl; 33 | } 34 | } 35 | 36 | int main() { 37 | std::ios_base::sync_with_stdio(false); 38 | 39 | int n; 40 | std::cin >> n; 41 | while (n) { 42 | testcase(n); 43 | std::cin >> n; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Week01/EvenMatrices/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | typedef std::vector> IMAT; 10 | 11 | void testcase() { 12 | int n; std::cin >> n; 13 | IMAT m(n + 1, std::vector(n + 1, 0)); 14 | 15 | for (int i = 1; i <= n; i++) 16 | for (int j = 1; j <= n; j++) { 17 | int a; std::cin >> a; 18 | m[i][j] = a - m[i - 1][j - 1] + m[i - 1][j] + m[i][j - 1]; 19 | } 20 | 21 | int sum = 0; 22 | for (int i1 = 1; i1 <= n; i1++) 23 | for (int i2 = i1; i2 <= n; i2++){ 24 | int even = 1, odd = 0; 25 | 26 | for (int j = 1, s = 0; j <= n; j++){ 27 | s += m[i2][j] + m[i1 - 1][j - 1] - m[i1 - 1][j] - m[i2][j - 1]; 28 | 29 | if (s % 2) { 30 | odd++; 31 | } else { 32 | even++; 33 | } 34 | } 35 | 36 | sum += (even * (even - 1)) / 2 + (odd * (odd - 1)) / 2; 37 | } 38 | 39 | std::cout << sum << std::endl; 40 | } 41 | 42 | int main() { 43 | std::ios_base::sync_with_stdio(false); 44 | 45 | int t; 46 | std::cin >> t; 47 | for (int i = 0; i < t; ++i) 48 | testcase(); 49 | } 50 | -------------------------------------------------------------------------------- /Week03/JamesBondSovereigns/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | void testcase() { 11 | int n, m, k; std::cin >> n >> m >> k; 12 | std::vector coins(n, 0); 13 | std::vector> dp(n , std::vector(n, 0)); 14 | 15 | for (int i = 0; i < n; i++) 16 | std::cin >> coins[i]; 17 | 18 | if ((n - 1) % m == k) 19 | for (int i = 0; i < n; i++) 20 | dp[i][i] = coins[i]; 21 | 22 | for (int i = n - 2; i >= 0; i--) { 23 | for (int j = i + 1; j < n; j++) { 24 | int curr_player = (n + i - j - 1) % m; 25 | 26 | if (curr_player == k) 27 | dp[i][j] = std::max(coins[i] + dp[i + 1][j], coins[j] + dp[i][j - 1]); 28 | else 29 | dp[i][j] = std::min(dp[i + 1][j], dp[i][j - 1]); 30 | } 31 | } 32 | 33 | std::cout << dp[0][n - 1] << std::endl; 34 | } 35 | 36 | int main() { 37 | std::ios_base::sync_with_stdio(false); 38 | std::cin.tie(NULL); 39 | 40 | int t; 41 | std::cin >> t; 42 | for (int i = 0; i < t; ++i) 43 | testcase(); 44 | } 45 | -------------------------------------------------------------------------------- /Week07/Octopussy/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | int take_subtree(std::vector& taken, const int root) { 10 | if (root >= (int)taken.size() || taken[root]) 11 | return 0; 12 | 13 | taken[root] = true; 14 | return 1 + take_subtree(taken, root * 2 + 1) + take_subtree(taken, root * 2 + 2); 15 | } 16 | 17 | void testcase() { 18 | int n; std::cin >> n; 19 | std::vector> t(n); 20 | std::vector taken(n, false); 21 | 22 | for (int i = 0; i < n; i++) { 23 | int ti; std::cin >> ti; 24 | t[i] = std::make_pair(ti, i); 25 | } 26 | 27 | std::sort(t.begin(), t.end()); 28 | 29 | int time = 0; 30 | for (const auto& i: t) { 31 | int next_time = i.first, next = i.second; 32 | 33 | time += take_subtree(taken, next); 34 | if (time > next_time) { 35 | std::cout << "no" << std::endl; 36 | return; 37 | } 38 | } 39 | 40 | std::cout << "yes" << std::endl; 41 | } 42 | 43 | int main() { 44 | std::ios_base::sync_with_stdio(false); 45 | 46 | int t; 47 | std::cin >> t; 48 | for (int i = 0; i < t; ++i) 49 | testcase(); 50 | } 51 | -------------------------------------------------------------------------------- /CppIntroduction/BFS/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | typedef struct node { 12 | int distance; 13 | std::set edges; 14 | 15 | node(): distance(-1), edges({}) {} 16 | } node_t; 17 | 18 | void bfs(std::vector &g, int root) { 19 | std::queue q = {}; 20 | 21 | g[root].distance = 0; 22 | q.push(root); 23 | 24 | while (!q.empty()) { 25 | int curr = q.front(); 26 | q.pop(); 27 | 28 | for (const auto child: g[curr].edges) 29 | if (g[child].distance == -1) { 30 | g[child].distance = g[curr].distance + 1; 31 | q.push(child); 32 | } 33 | } 34 | } 35 | 36 | void testcase() { 37 | int n, m, v; std::cin >> n >> m >> v; 38 | std::vector g(n, node()); 39 | 40 | while (m--) { 41 | int a, b; std::cin >> a >> b; 42 | g[a].edges.insert(b); 43 | g[b].edges.insert(a); 44 | } 45 | 46 | bfs(g, v); 47 | 48 | for (const auto n: g) 49 | std::cout << n.distance << " "; 50 | std::cout << std::endl; 51 | } 52 | 53 | int main() { 54 | std::ios_base::sync_with_stdio(false); 55 | 56 | int t; 57 | std::cin >> t; 58 | for (int i = 0; i < t; ++i) 59 | testcase(); 60 | } 61 | -------------------------------------------------------------------------------- /CppIntroduction/DFS/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | typedef struct node { 12 | int discovery, completion; 13 | std::set edges; 14 | 15 | node(): discovery(-1), completion(-1), edges({}) {} 16 | } node_t; 17 | 18 | int dfs(std::vector &g, int curr, int step) { 19 | g[curr].discovery = step++; 20 | for (const auto child: g[curr].edges) 21 | if (g[child].discovery == -1) 22 | step = dfs(g, child, step); 23 | 24 | g[curr].completion = step++; 25 | return step; 26 | } 27 | 28 | void testcase() { 29 | int n, m, v; std::cin >> n >> m >> v; 30 | std::vector g(n, node()); 31 | 32 | while (m--) { 33 | int a, b; std::cin >> a >> b; 34 | g[a].edges.insert(b); 35 | g[b].edges.insert(a); 36 | } 37 | 38 | dfs(g, v, 0); 39 | 40 | for (const auto n: g) 41 | std::cout << n.discovery << " "; 42 | std::cout << std::endl; 43 | 44 | for (const auto n: g) 45 | std::cout << n.completion << " "; 46 | std::cout << std::endl; 47 | } 48 | 49 | int main() { 50 | std::ios_base::sync_with_stdio(false); 51 | 52 | int t; 53 | std::cin >> t; 54 | for (int i = 0; i < t; ++i) 55 | testcase(); 56 | } 57 | -------------------------------------------------------------------------------- /Week04/Antenna/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | using K = CGAL::Exact_predicates_exact_constructions_kernel_with_sqrt; 14 | using P = K::Point_2; 15 | using Traits = CGAL::Min_circle_2_traits_2; 16 | using MC = CGAL::Min_circle_2; 17 | 18 | double ceil_to_double(const K::FT& x) 19 | { 20 | double a = std::ceil(CGAL::to_double(x)); 21 | while (a + 1 > x) a--; 22 | while (a < x) a++; 23 | return a; 24 | } 25 | 26 | void testcase(int n) 27 | { 28 | std::vector

points(n); 29 | 30 | for (int i = 0; i < n; i++) { 31 | long x, y; std::cin >> x >> y; 32 | points[i] = P(x, y); 33 | } 34 | 35 | MC mc(points.begin(), points.end(), true); 36 | Traits::Circle c = mc.circle(); 37 | std::cout << std::setprecision(0) << std::fixed; 38 | std::cout << ceil_to_double(CGAL::sqrt(c.squared_radius())) << std::endl; 39 | } 40 | 41 | int main() 42 | { 43 | std::ios_base::sync_with_stdio(false); 44 | 45 | int n; std::cin >> n; 46 | while (n) { 47 | testcase(n); 48 | std::cin >> n; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Week11/Legions/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | typedef long IT; 14 | typedef CGAL::Gmpz ET; 15 | 16 | typedef CGAL::Quadratic_program Program; 17 | typedef CGAL::Quadratic_program_solution Solution; 18 | 19 | void testcase() { 20 | long xs, ys, n; std::cin >> xs >> ys >> n; 21 | 22 | Program lp (CGAL::SMALLER, false, 0, false, 0); 23 | const int T = 0, X = 1, Y = 2; 24 | lp.set_l(T, true, 0); 25 | lp.set_c(T, -1); 26 | 27 | for (int i = 0; i < n; i++) { 28 | long a, b, c, v; std::cin >> a >> b >> c >> v; 29 | long sign = a * xs + b * ys + c >= 0 ? 1 : -1; 30 | long norm = std::floor(std::sqrt(a * a + b * b)); 31 | 32 | lp.set_a(X, i, -a * sign); 33 | lp.set_a(Y, i, -b * sign); 34 | lp.set_a(T, i, norm * v); 35 | lp.set_b(i, c * sign); 36 | } 37 | 38 | Solution s = CGAL::solve_linear_program(lp, ET()); 39 | std::cout << (long)std::floor(CGAL::to_double(*s.variable_values_begin())) << std::endl; 40 | } 41 | 42 | int main() { 43 | std::ios_base::sync_with_stdio(false); 44 | 45 | int t; 46 | std::cin >> t; 47 | for (int i = 0; i < t; ++i) 48 | testcase(); 49 | } 50 | -------------------------------------------------------------------------------- /CppIntroduction/Vectors/cx_description/english.md: -------------------------------------------------------------------------------- 1 | # Vectors 2 | In this exercise you are supposed to do some operations with vectors. 3 | 4 | ## Input 5 | 6 | The first line of the input contains the number $t \leq 10$ of test 7 | cases. Each of the $t$ test cases is described as follows. 8 | 9 | - It starts with a line that contains an integer `n`, such that $0 10 | \leq n \leq 10$. 11 | 12 | - The following line contains $n$ integers $\verb|a|_0\ \ldots\ 13 | \verb|a|_{n - 1}$, separated by a space, such that 14 | $-1000 \leq a_i \leq 15 | 1000$, for all $i \in \{0, \ldots, n - 1\}$. 16 | 17 | - The following line contains an integer `d`, denoting the index of an 18 | element that is to be removed from the vector, and such that 19 | $0 \leq d 20 | \leq n - 1$. 21 | 22 | - The following line contains two integers `a b`, separated by a 23 | space, denoting the range of indices of the elements that should be 24 | removed from the *remaining* vector (both inclusive), and such that 25 | $0 \leq a \leq b \leq n - 2$. 26 | 27 | ## Output 28 | 29 | For each test case output one line with the remaining elements of the 30 | vector separated by a space. If there are no elements remaining in the 31 | vector output '`Empty`'. 32 | 33 | ## Points 34 | 35 | There is one group of test sets, worth $100$ points in total. -------------------------------------------------------------------------------- /Week08/Diet/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | using IT = int; 14 | using ET = CGAL::Gmpz; 15 | using Program = CGAL::Quadratic_program; 16 | using Solution = CGAL::Quadratic_program_solution; 17 | 18 | void testcase(const int n, const int m) { 19 | Program lp(CGAL::SMALLER, true, 0, false, 0); 20 | 21 | for (int i = 0; i < n; i++) { 22 | int min, max; std::cin >> min >> max; 23 | lp.set_b(2*i, -min); 24 | lp.set_b(2*i + 1, max); 25 | } 26 | 27 | for (int i = 0; i < m; i++) { 28 | int p; std::cin >> p; 29 | lp.set_c(i, p); 30 | 31 | for (int j = 0; j < n; j++) { 32 | int c; std::cin >> c; 33 | lp.set_a(i, 2*j, -c); 34 | lp.set_a(i, 2*j + 1, c); 35 | } 36 | } 37 | 38 | Solution s = CGAL::solve_linear_program(lp, ET()); 39 | 40 | if (s.is_infeasible()) 41 | std::cout << "No such diet." << std::endl; 42 | else 43 | std::cout << (long)std::floor(CGAL::to_double(s.objective_value())) << std::endl; 44 | } 45 | 46 | int main() { 47 | std::ios_base::sync_with_stdio(false); 48 | 49 | int n, m; std::cin >> n >> m; 50 | while (n) { 51 | testcase(n, m); 52 | std::cin >> n >> m; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /CppIntroduction/DFS/cx_description/english.md: -------------------------------------------------------------------------------- 1 | # DFS 2 | 3 | Compute the DFS timestamps of discovery and finishing of all vertices 4 | starting from a given vertex. The order in which the DFS traversal 5 | visits the vertices should be such that it *always* visits the unvisited 6 | neighbour of the current vertex *with the smallest identifier*. 7 | 8 | ## Input 9 | 10 | The first line of the input contains the number $t \leq 10$ of test 11 | cases. Each of the $t$ test cases is described as follows. 12 | 13 | - It starts with a line that contains three integers `n m v`, 14 | separated by a space, denoting the number of vertices, the number of 15 | edges, and the starting vertex, and such that $0 \leq n \leq 10^3$, 16 | $0 17 | \leq m \leq \binom{n}{2}$, and $0 \leq v \leq n - 1$. 18 | 19 | - The following $m$ lines each contain two integers `a b`, separated 20 | by a space, indicating that $\{a, b\}$ is an edge of the graph. 21 | 22 | ## Output 23 | 24 | For each test case you should output two lines: the first containing the 25 | timestamps of discovery separated by a space and ordered by increasing 26 | labels; the second containing timestamps of finishing separated by a 27 | space and ordered by increasing labels. If a vertex cannot be reached, 28 | both of its timestamps are $-1$. 29 | 30 | ## Points 31 | 32 | There is one group of test sets, worth $100$ points in total. -------------------------------------------------------------------------------- /Week08/Inball/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | using IT = int; 14 | using ET = CGAL::Gmpz; 15 | using Program = CGAL::Quadratic_program; 16 | using Solution = CGAL::Quadratic_program_solution; 17 | 18 | void testcase(const int n) { 19 | int d; std::cin >> d; 20 | Program lp(CGAL::SMALLER, false, 0, false, 0); 21 | 22 | const int R = 0; 23 | lp.set_l(R, true, 0); 24 | lp.set_c(R, -1); 25 | 26 | for (int i = 0; i < n; i++) { 27 | int norm = 0; 28 | 29 | for (int j = 1; j <= d; j++) { 30 | int a; std::cin >> a; 31 | lp.set_a(j, i, a); 32 | norm += a * a; 33 | } 34 | norm = std::floor(std::sqrt(norm)); 35 | lp.set_a(R, i, norm); 36 | 37 | int b; std::cin >> b; 38 | lp.set_b(i, b); 39 | } 40 | 41 | Solution s = CGAL::solve_linear_program(lp, ET()); 42 | if (s.is_infeasible()) 43 | std::cout << "none" << std::endl; 44 | else if (s.is_unbounded()) 45 | std::cout << "inf" << std::endl; 46 | else 47 | std::cout << (long)std::floor(CGAL::to_double(*s.variable_values_begin())) << std::endl; 48 | } 49 | 50 | int main() { 51 | std::ios_base::sync_with_stdio(false); 52 | 53 | int n; std::cin >> n; 54 | while (n) { 55 | testcase(n); 56 | std::cin >> n; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Week02/BurningCoins/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | typedef std::vector>> MEMO; 10 | 11 | std::pair search(MEMO& memo, std::vector &v, const int i, const int j, const int side) { 12 | if (i == j) 13 | return std::make_pair(0, 0); 14 | 15 | if (memo[i][j].first != -1) 16 | return memo[i][j]; 17 | 18 | auto pick_start = search(memo, v, i + 1, j, 1 - side); 19 | int start_val = v[i] + (side ? pick_start.second : pick_start.first); 20 | 21 | auto pick_end = search(memo, v, i, j - 1, 1 - side); 22 | int end_val = v[j - 1] + (side ? pick_end.second : pick_end.first); 23 | 24 | if (start_val > end_val) 25 | memo[i][j] = std::make_pair(side ? pick_start.first : start_val, side ? start_val : pick_start.second); 26 | else 27 | memo[i][j] = std::make_pair(side ? pick_end.first : end_val, side ? end_val : pick_end.second); 28 | 29 | return memo[i][j]; 30 | } 31 | 32 | void testcase() { 33 | int n; std::cin >> n; 34 | std::vector v(n); 35 | 36 | for (auto& i: v) 37 | std::cin >> i; 38 | 39 | MEMO memo(n + 1, std::vector>(n + 1, std::make_pair(-1, -1))); 40 | std::cout << search(memo, v, 0, n, 0).first << std::endl; 41 | } 42 | 43 | int main() { 44 | std::ios_base::sync_with_stdio(false); 45 | 46 | int t; 47 | std::cin >> t; 48 | for (int i = 0; i < t; ++i) 49 | testcase(); 50 | } 51 | -------------------------------------------------------------------------------- /Week03/ImportantBridges/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | using Graph = boost::adjacency_list; 14 | using EdgeDesc = boost::graph_traits::edge_descriptor; 15 | 16 | void testcase() { 17 | int n, m; std::cin >> n >> m; 18 | Graph g(n); 19 | std::map map; 20 | 21 | for (int i = 0; i < m; i++) { 22 | int a, b; std::cin >> a >> b; 23 | boost::add_edge(a, b, g); 24 | } 25 | 26 | auto bc = boost::biconnected_components(g, boost::make_assoc_property_map(map)); 27 | 28 | std::vector counts(bc, 0); 29 | for (const auto i: map) 30 | counts[i.second]++; 31 | 32 | int k = 0; 33 | std::set> critical; 34 | for (const auto i: map) 35 | if (counts[i.second] == 1) { 36 | k++; 37 | 38 | int src = boost::source(i.first, g), tgt = boost::target(i.first, g); 39 | critical.insert(std::make_pair(std::min(src, tgt), std::max(src, tgt))); 40 | } 41 | 42 | std::cout << k << std::endl; 43 | for (const auto i: critical) 44 | std::cout << i.first << " " << i.second << "\n"; 45 | } 46 | 47 | int main() { 48 | std::ios_base::sync_with_stdio(false); 49 | 50 | int t; 51 | std::cin >> t; 52 | for (int i = 0; i < t; ++i) 53 | testcase(); 54 | } 55 | -------------------------------------------------------------------------------- /Week12/PiedPiper/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | typedef std::vector>> adjacency; 11 | typedef std::vector> dp; 12 | 13 | void testcase() { 14 | int n, m; std::cin >> n >> m; 15 | adjacency fwd_adj(n, std::vector>()); 16 | adjacency bwd_adj(n, std::vector>()); 17 | dp dp(n, std::vector(n, -1)); 18 | 19 | for (int i = 0; i < m; i++) { 20 | int u, v, f; std::cin >> u >> v >> f; 21 | 22 | if (u < v) 23 | fwd_adj[u].push_back({v, f}); 24 | else 25 | bwd_adj[v].push_back({u, f}); 26 | } 27 | 28 | dp[0][0] = 0; 29 | for (int sum = 0; sum <= 2*(n - 1); sum++) { 30 | for (int i = 0; i <= sum; i++) { 31 | int j = sum - i; 32 | 33 | if (i >= n 34 | || j >= n 35 | || (i == j && i != 0) 36 | || dp[i][j] == -1) 37 | continue; 38 | 39 | for (const auto [next_i, p_i]: fwd_adj[i]) 40 | if (next_i >= j) 41 | dp[next_i][j] = std::max(dp[next_i][j], dp[i][j] + p_i); 42 | 43 | for (const auto [next_j, p_j]: bwd_adj[j]) 44 | if (next_j >= i) 45 | dp[i][next_j] = std::max(dp[i][next_j], dp[i][j] + p_j); 46 | } 47 | } 48 | 49 | std::cout << dp[n - 1][n - 1] << std::endl; 50 | } 51 | 52 | int main() { 53 | std::ios_base::sync_with_stdio(false); 54 | 55 | int t; 56 | std::cin >> t; 57 | for (int i = 0; i < t; ++i) 58 | testcase(); 59 | } 60 | -------------------------------------------------------------------------------- /Week11/AsterixChariotRace/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | std::vector> stages; 11 | std::vector costs; 12 | 13 | std::tuple solve(const int src) { 14 | if (stages[src].size() == 0) 15 | return {costs[src], costs[src], 0}; 16 | 17 | long fix_me = costs[src], parent_save = 0; 18 | long best_child = std::numeric_limits::max(); 19 | 20 | for (const auto& s: stages[src]) { 21 | auto [fix_child, child_saved, save_child] = solve(s); 22 | long child_safe = std::min(fix_child, child_saved); 23 | 24 | fix_me += std::min(save_child, child_safe); 25 | parent_save += child_safe; 26 | best_child = std::min(best_child, fix_child - child_safe); 27 | } 28 | 29 | return {fix_me, parent_save + best_child, parent_save}; 30 | } 31 | 32 | void testcase() { 33 | int n; std::cin >> n; 34 | stages = std::vector>(n, std::vector()); 35 | costs = std::vector(n); 36 | 37 | for (int i = 0; i < n - 1; i++) { 38 | int a, b; std::cin >> a >> b; 39 | stages[a].push_back(b); 40 | } 41 | 42 | for (int i = 0; i < n; i++) 43 | std::cin >> costs[i]; 44 | 45 | auto monza = solve(0); 46 | std::cout << std::min(std::get<0>(monza), std::get<1>(monza)) << std::endl; 47 | } 48 | 49 | int main() { 50 | std::ios_base::sync_with_stdio(false); 51 | 52 | int t; 53 | std::cin >> t; 54 | for (int i = 0; i < t; ++i) 55 | testcase(); 56 | } 57 | -------------------------------------------------------------------------------- /Week03/FirstStepsBGL/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | using WeightedGraph = boost::adjacency_list< 15 | boost::vecS, 16 | boost::vecS, 17 | boost::undirectedS, 18 | boost::no_property, 19 | boost::property 20 | >; 21 | using EdgeDesc = boost::graph_traits::edge_descriptor; 22 | 23 | void testcase() { 24 | int n, m; std::cin >> n >> m; 25 | WeightedGraph g(n); 26 | std::vector mst; 27 | std::vector dist_map(n); 28 | 29 | while (m--) { 30 | int src, tgt, weight; std::cin >> src >> tgt >> weight; 31 | boost::add_edge(src, tgt, weight, g); 32 | } 33 | boost::kruskal_minimum_spanning_tree(g, std::back_inserter(mst)); 34 | 35 | int total = 0; 36 | for (const auto &i: mst) 37 | total += boost::get(boost::edge_weight_t(), g, i); 38 | 39 | boost::dijkstra_shortest_paths(g, 0,boost::distance_map( 40 | boost::make_iterator_property_map(dist_map.begin(), boost::get(boost::vertex_index, g))) 41 | ); 42 | 43 | int max = -1; 44 | for (const auto &i: dist_map) 45 | max = std::max(i, max); 46 | 47 | std::cout << total << " " << max << std::endl; 48 | } 49 | 50 | int main() { 51 | std::ios_base::sync_with_stdio(false); 52 | 53 | int t; 54 | std::cin >> t; 55 | for (int i = 0; i < t; ++i) 56 | testcase(); 57 | } 58 | -------------------------------------------------------------------------------- /Week02/TheGreatGame/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | typedef std::vector> ADJ; 11 | typedef std::vector> DP; 12 | 13 | int search(ADJ const &adj, DP &dp, const unsigned int pos, const bool minimize) { 14 | if (pos == dp.size() - 1) 15 | return 0; 16 | else { 17 | int memo = minimize ? dp[pos].second : dp[pos].first; 18 | 19 | if (memo != -1) 20 | return memo; 21 | } 22 | 23 | int res = minimize ? std::numeric_limits::max() : std::numeric_limits::min(); 24 | for (const auto tgt: adj[pos]) 25 | if (minimize) 26 | res = std::min(res, 1 + search(adj, dp, tgt, false)); 27 | else 28 | res = std::max(res, 1 + search(adj, dp, tgt, true)); 29 | 30 | if (minimize) { 31 | dp[pos].second = res; 32 | } else { 33 | dp[pos].first = res; 34 | } 35 | 36 | return res; 37 | } 38 | 39 | void testcase() { 40 | int n, m, r, b; std::cin >> n >> m >> r >> b; 41 | ADJ adj(n + 1, std::vector()); 42 | DP dp(n + 1, std::pair(-1, -1)); 43 | 44 | for (int i = 0; i < m; i++) { 45 | int u, v; std::cin >> u >> v; 46 | adj[u].push_back(v); 47 | } 48 | 49 | int red = search(adj, dp, r, true); 50 | int black = search(adj, dp, b, true); 51 | 52 | std::cout << (((red < black) || (red == black && red % 2 != 0)) ? '0' : '1') << std::endl; 53 | } 54 | 55 | int main() { 56 | std::ios_base::sync_with_stdio(false); 57 | 58 | int t; 59 | std::cin >> t; 60 | for (int i = 0; i < t; ++i) 61 | testcase(); 62 | } 63 | -------------------------------------------------------------------------------- /Week03/BuddySelection/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | using Graph = boost::adjacency_list; 14 | using VertexDesc = boost::graph_traits::vertex_descriptor; 15 | 16 | void testcase() { 17 | int n, c, f; std::cin >> n >> c >> f; 18 | std::vector> s(n, std::unordered_set{}); 19 | std::vector mate_map(n); 20 | Graph g(n); 21 | 22 | for (int i = 0; i < n; i++) { 23 | for (int j = 0; j < c; j++) { 24 | std::string x; std::cin >> x; 25 | s[i].insert(x); 26 | } 27 | 28 | for (int j = 0; j < i; j++) { 29 | int count = 0; 30 | for (const auto &p: s[i]) { 31 | if (s[j].find(p) != s[j].end()) 32 | count++; 33 | 34 | if (count > f) { 35 | boost::add_edge(i, j, g); 36 | break; 37 | } 38 | } 39 | } 40 | } 41 | 42 | boost::edmonds_maximum_cardinality_matching( 43 | g, 44 | boost::make_iterator_property_map(mate_map.begin(), boost::get(boost::vertex_index, g)) 45 | ); 46 | 47 | std::string res = "not optimal"; 48 | for (const auto &i: mate_map) 49 | if (mate_map[i] >= (unsigned long int)n) { // null vertex is broken for some reason??? 50 | res = "optimal"; 51 | break; 52 | } 53 | 54 | std::cout << res << std::endl; 55 | } 56 | 57 | int main() { 58 | std::ios_base::sync_with_stdio(false); 59 | 60 | int t; 61 | std::cin >> t; 62 | for (int i = 0; i < t; ++i) 63 | testcase(); 64 | } 65 | -------------------------------------------------------------------------------- /Week02/BeachBars/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define MAX 1000001 11 | #define R 100 12 | 13 | void testcase() { 14 | int n; std::cin >> n; 15 | std::vector beach(2 * MAX + 2 * R, false); 16 | 17 | for (int i = 0; i < n; i++) { 18 | int x; std::cin >> x; 19 | beach[x + MAX + R] = true; 20 | } 21 | 22 | int best = 0, total = 0; 23 | for (int i = R; i <= 2 * R; i++) 24 | total += beach[i]; 25 | 26 | std::vector totals(2 * MAX + 2 * R, 0); 27 | totals[R] = total; 28 | for (int i = R + 1; i < 2 * MAX + R; i++) { 29 | if (beach[i - R - 1]) 30 | total--; 31 | if (beach[i + R]) 32 | total++; 33 | 34 | totals[i] = total; 35 | best = std::max(best, total); 36 | } 37 | 38 | std::vector distances(2 * MAX + 2 * R, std::numeric_limits::max()); 39 | int closest = std::numeric_limits::max(); 40 | for (int i = R; i < 2 * MAX + R; i++) { 41 | if (totals[i] != best) 42 | continue; 43 | 44 | for (int j = R; j >= 0; j--) { 45 | if (beach[i - j] || beach[i + j]) { 46 | distances[i] = j; 47 | break; 48 | } 49 | } 50 | 51 | closest = std::min(closest, distances[i]); 52 | } 53 | 54 | std::vector optimal; 55 | optimal.reserve(2 * MAX); 56 | for (int i = R; i < 2 * MAX + R; i++) 57 | if (totals[i] == best && distances[i] == closest) 58 | optimal.push_back(i); 59 | 60 | std::cout << best << " " << closest << std::endl; 61 | for (const int x: optimal) 62 | std::cout << x - MAX - R << " "; 63 | std::cout << std::endl; 64 | } 65 | 66 | int main() { 67 | std::ios_base::sync_with_stdio(false); 68 | 69 | int t; 70 | std::cin >> t; 71 | for (int i = 0; i < t; ++i) 72 | testcase(); 73 | } 74 | -------------------------------------------------------------------------------- /Week07/Germs/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | using K = CGAL::Exact_predicates_inexact_constructions_kernel; 14 | using P = K::Point_2; 15 | using Triangulation = CGAL::Delaunay_triangulation_2; 16 | 17 | int time_of_death(K::FT& square_dist) 18 | { 19 | if (square_dist <= 1) 20 | return 0; 21 | 22 | K::FT d = CGAL::sqrt(square_dist); 23 | return (int) std::ceil(CGAL::sqrt((d - 1) / 2)); 24 | } 25 | 26 | void testcase(int n) 27 | { 28 | long l, b, r, t; std::cin >> l >> b >> r >> t; 29 | Triangulation tr; 30 | std::vector

points(n); 31 | 32 | for (int i = 0; i < n; i++) { 33 | int x, y; std::cin >> x >> y; 34 | points[i] = P(x, y); 35 | } 36 | 37 | tr.insert(points.begin(), points.end()); 38 | 39 | std::vector dists; 40 | for (auto vh: tr.finite_vertex_handles()) { 41 | auto neighbor = CGAL::nearest_neighbor(tr, vh); 42 | long n_dist = CGAL::squared_distance(vh->point(), neighbor->point()); 43 | 44 | long x = vh->point().x(), y = vh->point().y(); 45 | long r_dist = std::min(r - x, std::min(x - l, std::min(t - y, y - b))); 46 | r_dist = 4 * r_dist * r_dist; 47 | 48 | dists.push_back(CGAL::min(r_dist, n_dist)); 49 | } 50 | 51 | std::sort(dists.begin(), dists.end()); 52 | 53 | int first = time_of_death(dists[0]); 54 | int half = time_of_death(dists[n / 2]); 55 | int last = time_of_death(dists[n - 1]); 56 | 57 | std::cout << first << " " << half << " " << last << std::endl; 58 | } 59 | 60 | int main() 61 | { 62 | std::ios_base::sync_with_stdio(false); 63 | 64 | int n; std::cin >> n; 65 | while (n) { 66 | testcase(n); 67 | std::cin >> n; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /PreviousYears/2022/Evolution/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | void testcase() { 11 | int n, q; std::cin >> n >> q; 12 | std::unordered_map s2i; 13 | std::vector i2s(n); 14 | std::vector leaf(n, true); 15 | std::vector ages(n),pred_map(n, -1); 16 | 17 | std::vector>> lists; 18 | std::vector> lookup(n); 19 | 20 | for (int i = 0; i < n; i++) { 21 | std::string s; std::cin >> s; 22 | int a; std::cin >> a; 23 | 24 | i2s[i] = s; 25 | s2i[s] = i; 26 | ages[i] = a; 27 | } 28 | 29 | for (int i = 1; i < n; i++) { 30 | std::string s, p; std::cin >> s >> p; 31 | pred_map[s2i[s]] = s2i[p]; 32 | leaf[s2i[p]] = false; 33 | } 34 | 35 | for (int i = 0; i < n; i++) { 36 | if (!leaf[i]) 37 | continue; 38 | 39 | int list_idx = lists.size(); 40 | lookup[i] = {list_idx, 0}; 41 | lists.push_back({{ages[i], i}}); 42 | 43 | for (int curr = pred_map[i]; curr != -1; curr = pred_map[curr]) { 44 | lookup[curr] = {list_idx, lists[list_idx].size()}; 45 | lists[list_idx].push_back({ages[curr], curr}); 46 | } 47 | } 48 | 49 | for (int i = 0; i < q; i++) { 50 | std::string s; std::cin >> s; 51 | int b; std::cin >> b; 52 | 53 | auto l = lookup[s2i[s]]; 54 | int start = l.second, end = lists[l.first].size(); 55 | while (start < end) { 56 | int mid = start + (end - start) / 2; 57 | 58 | if (lists[l.first][mid].first <= b) 59 | start = mid + 1; 60 | else 61 | end = mid; 62 | } 63 | 64 | std::cout << i2s[lists[l.first][start - 1].second] << " "; 65 | } 66 | std::cout << std::endl; 67 | } 68 | 69 | int main() { 70 | std::ios_base::sync_with_stdio(false); 71 | 72 | int t; 73 | std::cin >> t; 74 | for (int i = 0; i < t; ++i) 75 | testcase(); 76 | } 77 | -------------------------------------------------------------------------------- /Week02/LordVoldemort/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | typedef std::vector> DP; 10 | 11 | int search( 12 | std::vector const &v, 13 | DP &dp, 14 | std::vector::const_iterator start, 15 | const int m, 16 | const int k 17 | ) { 18 | int idx = start - v.begin(); 19 | 20 | if (m == 0) 21 | return 0; 22 | else if (start == v.end()) 23 | return -1; 24 | else if (dp[idx][m] != -2) 25 | return dp[idx][m]; 26 | 27 | for (auto j = dp[idx].begin() + m - 1; j != dp[idx].begin(); j--) 28 | if (*j == -1) 29 | return -1; 30 | 31 | auto next_best = start; 32 | dp[idx][m] = -1; 33 | for (auto i = start; i != v.end(); i++) { 34 | if (*i != -1) { 35 | int rest = search(v, dp, i + *i, m - 1, k); 36 | 37 | if (rest != - 1 && rest + *i > dp[idx][m]) { 38 | dp[idx][m] = rest + *i; 39 | next_best = i; 40 | } 41 | } 42 | } 43 | 44 | for (auto i = next_best; i != start; i--) { 45 | dp[i - v.begin()][m] = dp[idx][m]; 46 | } 47 | 48 | return dp[idx][m]; 49 | } 50 | 51 | void testcase() { 52 | int n, m, k; std::cin >> n >> m >> k; 53 | std::vector v(n + 1, 0); 54 | DP dp(n + 1, std::vector(m + 1, -2)); 55 | 56 | for (int i = 1; i <= n; i++) { 57 | int x; std::cin >> x; 58 | v[i] = v[i - 1] + x; 59 | } 60 | 61 | for (auto i = v.begin(); i != v.end(); i++) { 62 | auto tgt = std::lower_bound(i + 1, v.end(), *i + k); 63 | 64 | if (tgt == v.end() || *tgt != *i + k) 65 | *i = -1; 66 | else 67 | *i = tgt - i; 68 | } 69 | 70 | int res = search(v, dp, v.begin(), m, k); 71 | if (res == -1) 72 | std::cout << "fail" << std::endl; 73 | else 74 | std::cout << res << std::endl; 75 | } 76 | 77 | int main() { 78 | std::ios_base::sync_with_stdio(false); 79 | 80 | int t; 81 | std::cin >> t; 82 | for (int i = 0; i < t; ++i) 83 | testcase(); 84 | } 85 | -------------------------------------------------------------------------------- /Week04/FirstHit/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | using K = CGAL::Exact_predicates_exact_constructions_kernel; 12 | using P = K::Point_2; 13 | using S = K::Segment_2; 14 | 15 | double floor_to_double(const K::FT& x) 16 | { 17 | double a = std::floor(CGAL::to_double(x)); 18 | while (a > x) a -= 1; 19 | while (a+1 <= x) a += 1; 20 | return a; 21 | } 22 | 23 | void testcase(long n) 24 | { 25 | long x, y, a, b; std::cin >> x >> y >> a >> b; 26 | P p1(x, y), p2(a, b); 27 | S best; 28 | K::Ray_2 ray(p1, p2); 29 | bool found = false; 30 | std::vector segments(n); 31 | 32 | for (int i = 0; i < n; i++) { 33 | long r, s, t, u; std::cin >> r >> s >> t >> u; 34 | P start(r, s), end(t, u); 35 | segments[i] = S(start, end); 36 | } 37 | 38 | std::random_shuffle(segments.begin(), segments.end()); 39 | for (const auto segment: segments) { 40 | auto result = found ? CGAL::intersection(best, segment) : CGAL::intersection(ray, segment); 41 | 42 | if (result) { 43 | found = true; 44 | 45 | if (const P* op = boost::get

(&*result)) 46 | best = S(p1, *op); 47 | else if (const S* os = boost::get(&*result)) { 48 | P d1 = os->start(), d2 = os->end(); 49 | 50 | if (CGAL::has_smaller_distance_to_point(p1, d1, d2)) 51 | best = S(p1, d1); 52 | else 53 | best = S(p1, d2); 54 | } 55 | } 56 | } 57 | 58 | if (!found) 59 | std::cout << "no" << std::endl; 60 | else { 61 | std::cout << std::setprecision(0) << std::fixed; 62 | std::cout << floor_to_double(best.end().x()) << " " << floor_to_double(best.end().y()) << std::endl; 63 | } 64 | } 65 | 66 | int main() 67 | { 68 | std::ios_base::sync_with_stdio(false); 69 | 70 | long n; std::cin >> n; 71 | while (n) { 72 | testcase(n); 73 | std::cin >> n; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /Week08/WhatIsTheMaximum/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | using IT = int; 14 | using ET = CGAL::Gmpz; 15 | using Program = CGAL::Quadratic_program; 16 | using Solution = CGAL::Quadratic_program_solution; 17 | 18 | const int X = 0, Y = 1, Z = 2; 19 | 20 | void p1(const int a, const int b) { 21 | Program lp(CGAL::SMALLER, true, 0, false, 0); 22 | 23 | lp.set_a(X, 0, 1); lp.set_a(Y, 0, 1); lp.set_b(0, 4); 24 | lp.set_a(X, 1, 4); lp.set_a(Y, 1, 2); lp.set_b(1, a * b); 25 | lp.set_a(X, 2, -1); lp.set_a(Y, 2, 1); lp.set_b(2, 1); 26 | 27 | lp.set_c(X, a); lp.set_c(Y, -b); 28 | 29 | Solution s = CGAL::solve_linear_program(lp, ET()); 30 | if (s.is_infeasible()) 31 | std::cout << "no" << std::endl; 32 | else if (s.is_unbounded()) 33 | std::cout << "unbounded" << std::endl; 34 | else 35 | std::cout << (long)std::floor(-CGAL::to_double(s.objective_value())) << std::endl; 36 | } 37 | 38 | void p2(const int a, const int b) { 39 | Program lp(CGAL::LARGER, false, 0, true, 0); 40 | 41 | lp.set_a(X, 0, 1); lp.set_a(Y, 0, 1); lp.set_b(0, -4); 42 | lp.set_a(X, 1, 4); lp.set_a(Y, 1, 2); lp.set_a(Z, 1, 1); lp.set_b(1, -a * b); 43 | lp.set_a(X, 2, -1); lp.set_a(Y, 2, 1); lp.set_b(2, -1); 44 | 45 | lp.set_c(X, a); lp.set_c(Y, b); lp.set_c(Z, 1); 46 | 47 | Solution s = CGAL::solve_linear_program(lp, ET()); 48 | if (s.is_infeasible()) 49 | std::cout << "no" << std::endl; 50 | else if (s.is_unbounded()) 51 | std::cout << "unbounded" << std::endl; 52 | else 53 | std::cout << (long)std::ceil(CGAL::to_double(s.objective_value())) << std::endl; 54 | } 55 | 56 | int main() { 57 | std::ios_base::sync_with_stdio(false); 58 | 59 | int p; std::cin >> p; 60 | while (p) { 61 | int a, b; std::cin >> a >> b; 62 | (p == 1) ? p1(a, b) : p2(a, b); 63 | std::cin >> p; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Week06/Motorcycles/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | using K = CGAL::Exact_predicates_exact_constructions_kernel; 12 | using P = K::Point_2; 13 | using R = K::Ray_2; 14 | 15 | struct Entry { 16 | long y; 17 | int i; 18 | R r; 19 | }; 20 | 21 | class StartPos { 22 | public: 23 | bool operator() (const Entry &o1, const Entry &o2) const { 24 | return o1.y < o2.y; 25 | } 26 | }; 27 | 28 | class Index { 29 | public: 30 | bool operator() (const Entry &o1, const Entry &o2) const { 31 | return o1.i < o2.i; 32 | } 33 | }; 34 | 35 | void testcase() { 36 | int n; std::cin >> n; 37 | P o1(0, 0), o2(0, 1); 38 | std::vector r(n); 39 | std::vector s; 40 | s.reserve(n); 41 | 42 | for (int i = 0; i < n; i++) { 43 | long y0, x1, y1; std::cin >> y0 >> x1 >> y1; 44 | P p1(0, y0), p2(x1, y1); 45 | r[i] = Entry({y0, i, R(p1, p2)}); 46 | } 47 | 48 | std::sort(r.begin(), r.end(), StartPos()); 49 | 50 | for (auto i = r.begin(); i != r.end(); i++) { 51 | bool add = true; 52 | 53 | for (auto j = s.rbegin(); j != s.rend(); j++) { 54 | auto intersect = CGAL::intersection(i->r, j->r); 55 | 56 | if (!intersect) 57 | break; 58 | else if (const P* itx = boost::get

(&*intersect)) { 59 | if (CGAL::left_turn(o1, o2, *itx)) 60 | break; 61 | 62 | if (CGAL::squared_distance(*itx, i->r.start()) >= CGAL::squared_distance(*itx, j->r.start())) { 63 | add = false; 64 | break; 65 | } else 66 | s.pop_back(); 67 | } 68 | } 69 | 70 | if (add) 71 | s.push_back(*i); 72 | } 73 | 74 | std::sort(s.begin(), s.end(), Index()); 75 | for (const auto& e: s) 76 | std::cout << e.i << " "; 77 | 78 | std::cout << std::endl; 79 | } 80 | 81 | int main() { 82 | std::ios_base::sync_with_stdio(false); 83 | 84 | int t; 85 | std::cin >> t; 86 | for (int i = 0; i < t; ++i) 87 | testcase(); 88 | } 89 | -------------------------------------------------------------------------------- /Week12/NewYork/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | typedef std::priority_queue> prio_q; 11 | 12 | int n, m, k; 13 | bool one_safe; 14 | 15 | prio_q q_max, q_min; 16 | std::vector prev, temps, parent; 17 | std::vector leaf, safe, visited; 18 | 19 | void testcase() { 20 | std::cin >> n >> m >> k; 21 | one_safe = false; 22 | 23 | prev = std::vector(n, -1); 24 | temps = std::vector(n); 25 | parent = std::vector(n); 26 | 27 | leaf = std::vector(n, true); 28 | safe = std::vector(n, false); 29 | visited = std::vector(n, false); 30 | 31 | for (int i = 0; i < n; i++) 32 | std::cin >> temps[i]; 33 | 34 | for (int i = 0; i < n - 1; i++) { 35 | int u, v; std::cin >> u >> v; 36 | prev[v] = u; 37 | leaf[u] = false; 38 | } 39 | 40 | for (int i = 0; i < n; i++) { 41 | if (leaf[i]) { 42 | int curr = i; 43 | q_max = prio_q(); 44 | q_min = prio_q(); 45 | 46 | for (int j = 0; curr != -1; j++, curr = prev[curr]) { 47 | parent[j] = curr; 48 | q_max.push({temps[curr], j}); 49 | q_min.push({-temps[curr], j}); 50 | 51 | while(q_max.top().second + m <= j) 52 | q_max.pop(); 53 | 54 | while(q_min.top().second + m <= j) 55 | q_min.pop(); 56 | 57 | if (j + 1 >= m) { 58 | if (q_max.top().first + q_min.top().first <= k) 59 | one_safe = safe[curr] = true; 60 | 61 | if (visited[parent[j + 1 - m]]) 62 | break; 63 | 64 | visited[parent[j + 1 - m]] = true; 65 | } 66 | } 67 | } 68 | } 69 | 70 | if (one_safe) { 71 | for (int i = 0; i < n; i++) 72 | if (safe[i]) 73 | std::cout << i << " "; 74 | 75 | std::cout << std::endl; 76 | } else 77 | std::cout << "Abort mission" << std::endl; 78 | } 79 | 80 | int main() { 81 | std::ios_base::sync_with_stdio(false); 82 | 83 | int t; 84 | std::cin >> t; 85 | for (int i = 0; i < t; ++i) 86 | testcase(); 87 | } 88 | -------------------------------------------------------------------------------- /Week05/PlanetExpress/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | using Graph = boost::adjacency_list< 15 | boost::vecS, 16 | boost::vecS, 17 | boost::directedS, 18 | boost::no_property, 19 | boost::property 20 | >; 21 | 22 | void testcase() { 23 | int n, m, k , t; std::cin >> n >> m >> k >> t; 24 | Graph g(2 * n); 25 | std::vector tp(n); 26 | 27 | for (int i = 0; i < t; i++){ 28 | int x; std::cin >> x; 29 | tp[i] = x; 30 | } 31 | 32 | for (int i = 0; i < m; i++) { 33 | int u, v, c; std::cin >> u >> v >> c; 34 | boost::add_edge(v, u, c, g); 35 | } 36 | 37 | std::vector scc(2 * n); 38 | int scc_count = boost::strong_components( 39 | g, 40 | boost::make_iterator_property_map(scc.begin(), boost::get(boost::vertex_index, g)) 41 | ); 42 | 43 | std::vector> subnets(scc_count); 44 | for (int i = 0; i < t; i++) 45 | subnets[scc[tp[i]]].push_back(tp[i]); 46 | 47 | for (int i = 0; i < scc_count; i++) { 48 | for (const auto src: subnets[i]) { 49 | boost::add_edge(n + i, src, 0, g); 50 | boost::add_edge(src, n + i, subnets[i].size() - 1, g); 51 | } 52 | } 53 | 54 | std::vector dists(2 * n); 55 | boost::dijkstra_shortest_paths( 56 | g, 57 | n - 1, 58 | boost::distance_map(boost::make_iterator_property_map(dists.begin(), boost::get(boost::vertex_index, g))) 59 | ); 60 | 61 | int min = 1000001; 62 | for (int i = 0; i < k; i++) 63 | min = std::min(min, dists[i]); 64 | 65 | if (min < 1000001) 66 | std::cout << min << std::endl; 67 | else 68 | std::cout << "no" << std::endl; 69 | } 70 | 71 | int main() { 72 | std::ios_base::sync_with_stdio(false); 73 | 74 | int t; 75 | std::cin >> t; 76 | for (int i = 0; i < t; ++i) 77 | testcase(); 78 | } 79 | -------------------------------------------------------------------------------- /PreviousYears/2022/Tracking/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | typedef boost::adjacency_list > graph; 15 | typedef boost::property_map::type weight_map; 16 | typedef boost::graph_traits::edge_descriptor edge_desc; 17 | typedef boost::graph_traits::vertex_descriptor vertex_desc; 18 | 19 | typedef std::vector>> adj; 20 | 21 | void testcase() { 22 | int n, m, k, x, y; std::cin >> n >> m >> k >> x >> y; 23 | adj river_adj = adj(n, std::vector>()); 24 | graph g(n + k); 25 | 26 | for (int i = 0; i < m; i++) { 27 | int a, b, c, d; std::cin >> a >> b >> c >> d; 28 | 29 | boost::add_edge(a, b, c, g); 30 | if (d) { 31 | river_adj[a].push_back({b, c}); 32 | river_adj[b].push_back({a, c}); 33 | } 34 | } 35 | 36 | std::vector dist_map(n + k); 37 | 38 | boost::dijkstra_shortest_paths(g, x, 39 | boost::distance_map(boost::make_iterator_property_map( 40 | dist_map.begin(), boost::get(boost::vertex_index, g)))); 41 | 42 | for (int j = 0; j < k; j++) { 43 | for (int i = 0; i < n; i++) { 44 | if (dist_map[i] == std::numeric_limits::max()) 45 | continue; 46 | 47 | for (const auto [tgt, c]: river_adj[i]) 48 | boost::add_edge(n + j, tgt, dist_map[i] + c, g); 49 | } 50 | 51 | boost::dijkstra_shortest_paths(g, n + j, 52 | boost::distance_map(boost::make_iterator_property_map( 53 | dist_map.begin(), boost::get(boost::vertex_index, g)))); 54 | } 55 | 56 | std::cout << dist_map[y] << std::endl; 57 | } 58 | 59 | int main() { 60 | std::ios_base::sync_with_stdio(false); 61 | 62 | int t; 63 | std::cin >> t; 64 | for (int i = 0; i < t; ++i) 65 | testcase(); 66 | } 67 | -------------------------------------------------------------------------------- /Week09/Algocoon/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | typedef boost::adjacency_list_traits traits; 14 | typedef boost::adjacency_list > > > graph; 18 | typedef boost::graph_traits::edge_descriptor edge_desc; 19 | typedef boost::graph_traits::out_edge_iterator out_edge_it; 20 | 21 | class edge_adder { 22 | graph &G; 23 | 24 | public: 25 | explicit edge_adder(graph &G) : G(G) {} 26 | 27 | void add_edge(int from, int to, long capacity) { 28 | auto c_map = boost::get(boost::edge_capacity, G); 29 | auto r_map = boost::get(boost::edge_reverse, G); 30 | const edge_desc e = boost::add_edge(from, to, G).first; 31 | const edge_desc rev_e = boost::add_edge(to, from, G).first; 32 | c_map[e] = capacity; 33 | c_map[rev_e] = 0; 34 | r_map[e] = rev_e; 35 | r_map[rev_e] = e; 36 | } 37 | }; 38 | 39 | void testcase() { 40 | int n, m; std::cin >> n >> m; 41 | graph g(n); 42 | edge_adder adder(g); 43 | 44 | for (int i = 0; i < m; i++) { 45 | int a, b, c; std::cin >> a >> b >> c; 46 | adder.add_edge(a, b, c); 47 | } 48 | 49 | long min_cut = std::numeric_limits::max(); 50 | for (int dst = 1; dst < n; dst++) { 51 | long forward = boost::push_relabel_max_flow(g, 0, dst); 52 | long backward = boost::push_relabel_max_flow(g, dst, 0); 53 | min_cut = std::min(min_cut, std::min(forward, backward)); 54 | } 55 | 56 | std::cout << min_cut << std::endl; 57 | } 58 | 59 | int main() { 60 | std::ios_base::sync_with_stdio(false); 61 | 62 | int t; 63 | std::cin >> t; 64 | for (int i = 0; i < t; ++i) 65 | testcase(); 66 | } 67 | -------------------------------------------------------------------------------- /Week03/AntChallenge/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | using Graph = boost::adjacency_list< 15 | boost::vecS, 16 | boost::vecS, 17 | boost::undirectedS, 18 | boost::no_property, 19 | boost::property 20 | >; 21 | using EdgeDesc = boost::graph_traits::edge_descriptor; 22 | using Weights = std::vector>>; 23 | 24 | void testcase() { 25 | int n, e, s, a, b; std::cin >> n >> e >> s >> a >> b; 26 | std::vector graphs(n + 1); 27 | Weights weights(n, std::vector>(n, std::vector(s, -1))); 28 | 29 | for (int i = 0; i < e; i++) { 30 | int src, tgt; std::cin >> src >> tgt; 31 | 32 | for (int j = 0; j < s; j++) { 33 | int w; std::cin >> w; 34 | 35 | boost::add_edge(src, tgt, w, graphs[j]); 36 | weights[src][tgt][j] = weights[tgt][src][j] = w; 37 | } 38 | } 39 | 40 | for (int species = 0; species < s; species++) { 41 | int h; std::cin >> h; 42 | std::vector pred(n); 43 | 44 | boost::prim_minimum_spanning_tree( 45 | graphs[species], 46 | boost::make_iterator_property_map(pred.begin(), boost::get(boost::vertex_index, graphs[species])), 47 | boost::root_vertex(h) 48 | ); 49 | 50 | for (int i = 0; i < n; i++) 51 | if (i != pred[i]) 52 | boost::add_edge(i, pred[i], weights[i][pred[i]][species], graphs[s]); 53 | } 54 | 55 | std::vector dist_map(n); 56 | boost::dijkstra_shortest_paths( 57 | graphs[s], 58 | a, 59 | boost::distance_map(boost::make_iterator_property_map(dist_map.begin(), boost::get(boost::vertex_index, graphs[s]))) 60 | ); 61 | 62 | std::cout << dist_map[b] << std::endl; 63 | } 64 | 65 | int main() { 66 | std::ios_base::sync_with_stdio(false); 67 | 68 | int t; 69 | std::cin >> t; 70 | for (int i = 0; i < t; ++i) 71 | testcase(); 72 | } 73 | -------------------------------------------------------------------------------- /Week10/SanFrancisco/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | typedef boost::adjacency_list 14 | > weighted_graph; 15 | typedef boost::property_map::type weight_map; 16 | typedef boost::graph_traits::edge_descriptor edge_desc; 17 | typedef boost::graph_traits::out_edge_iterator out_edge_it; 18 | 19 | typedef std::vector> dp; 20 | 21 | void fill_dp(weighted_graph& g, dp& dp, const int n, const int k) { 22 | weight_map weight_map = boost::get(boost::edge_weight, g); 23 | 24 | for (int d = 1; d <= k; d++) { 25 | for (int src = 0; src < n; src++){ 26 | long best = -1; 27 | out_edge_it oe_beg, oe_end; 28 | for (boost::tie(oe_beg, oe_end) = boost::out_edges(src, g); oe_beg != oe_end; ++oe_beg) { 29 | int tgt = boost::target(*oe_beg, g); 30 | long weight = weight_map[*oe_beg]; 31 | 32 | best = std::max(best, weight + dp[tgt][d - 1]); 33 | } 34 | 35 | dp[src][d] = (best == -1) ? dp[0][d] : best; 36 | } 37 | } 38 | } 39 | 40 | void testcase() { 41 | long n, m, x, k; std::cin >> n >> m >> x >> k; 42 | weighted_graph g(n); 43 | dp dp(n, std::vector(k + 2, 0)); 44 | 45 | for (int i = 0; i < m; i++) { 46 | int u, v, p; std::cin >> u >> v >> p; 47 | boost::add_edge(u, v, p, g); 48 | } 49 | 50 | fill_dp(g, dp, n, k); 51 | 52 | if (dp[0][k] < x) { 53 | std::cout << "Impossible" << std::endl; 54 | return; 55 | } 56 | 57 | long start = 0, end = k; 58 | while (start < end) { 59 | long mid = start + (end - start) / 2; 60 | 61 | if (dp[0][mid] < x) 62 | start = mid + 1; 63 | else 64 | end = mid; 65 | } 66 | 67 | std::cout << start << std::endl; 68 | } 69 | 70 | int main() { 71 | std::ios_base::sync_with_stdio(false); 72 | 73 | int t; 74 | std::cin >> t; 75 | for (int i = 0; i < t; ++i) 76 | testcase(); 77 | } 78 | -------------------------------------------------------------------------------- /Week11/PhantomMenace/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | typedef boost::adjacency_list_traits traits; 13 | typedef boost::adjacency_list>>> graph; 17 | 18 | typedef traits::vertex_descriptor vertex_desc; 19 | typedef traits::edge_descriptor edge_desc; 20 | 21 | class edge_adder { 22 | graph &G; 23 | 24 | public: 25 | explicit edge_adder(graph &G) : G(G) {} 26 | 27 | void add_edge(int from, int to, long capacity) { 28 | auto c_map = boost::get(boost::edge_capacity, G); 29 | auto r_map = boost::get(boost::edge_reverse, G); 30 | const auto e = boost::add_edge(from, to, G).first; 31 | const auto rev_e = boost::add_edge(to, from, G).first; 32 | c_map[e] = capacity; 33 | c_map[rev_e] = 0; 34 | r_map[e] = rev_e; 35 | r_map[rev_e] = e; 36 | } 37 | }; 38 | 39 | void testcase() { 40 | int n, m, s, d; std::cin >> n >> m >> s >> d; 41 | int src = 2*n, dst = src + 1; 42 | graph g(dst + 1); 43 | edge_adder adder(g); 44 | 45 | for (int i = 0; i < n; i++) 46 | adder.add_edge(2*i, 2*i + 1, 1); 47 | 48 | for (int i = 0; i < m; i++) { 49 | int a, b; std::cin >> a >> b; 50 | adder.add_edge(2*a + 1, 2*b, 1); 51 | } 52 | 53 | for (int i = 0; i < s; i++) { 54 | int a; std::cin >> a; 55 | adder.add_edge(src, 2*a, 1); 56 | } 57 | 58 | for (int i = 0; i < d; i++) { 59 | int a; std::cin >> a; 60 | adder.add_edge(2*a + 1, dst, 1); 61 | } 62 | 63 | std::cout << (long)boost::push_relabel_max_flow(g, src, dst) << std::endl; 64 | } 65 | 66 | int main() { 67 | std::ios_base::sync_with_stdio(false); 68 | 69 | int t; 70 | std::cin >> t; 71 | for (int i = 0; i < t; ++i) 72 | testcase(); 73 | } 74 | -------------------------------------------------------------------------------- /PreviousYears/2022/AsterixInSwitzerland/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | typedef boost::adjacency_list_traits traits; 14 | typedef boost::adjacency_list > > > graph; 18 | typedef boost::graph_traits::edge_descriptor edge_desc; 19 | typedef boost::graph_traits::out_edge_iterator out_edge_it; 20 | 21 | class edge_adder { 22 | graph &G; 23 | 24 | public: 25 | explicit edge_adder(graph &G) : G(G) {} 26 | 27 | void add_edge(int from, int to, long capacity) { 28 | auto c_map = boost::get(boost::edge_capacity, G); 29 | auto r_map = boost::get(boost::edge_reverse, G); 30 | const edge_desc e = boost::add_edge(from, to, G).first; 31 | const edge_desc rev_e = boost::add_edge(to, from, G).first; 32 | c_map[e] = capacity; 33 | c_map[rev_e] = 0; 34 | r_map[e] = rev_e; 35 | r_map[rev_e] = e; 36 | } 37 | }; 38 | 39 | void testcase() { 40 | int n, m; std::cin >> n >> m; 41 | int tot = 0, src = n, dst = src + 1; 42 | graph g(dst + 1); 43 | edge_adder adder(g); 44 | 45 | for (int i = 0; i < n; i++) { 46 | int b; std::cin >> b; 47 | 48 | if (b > 0) { 49 | tot += b; 50 | adder.add_edge(src, i, b); 51 | } else 52 | adder.add_edge(i, dst, -b); 53 | } 54 | 55 | for (int i = 0; i < m; i++) { 56 | int x, y, d; std::cin >> x >> y >> d; 57 | adder.add_edge(x, y, d); 58 | } 59 | 60 | long flow = boost::push_relabel_max_flow(g, src, dst); 61 | std::cout << ((tot > flow) ? "yes" : "no") << std::endl; 62 | } 63 | 64 | int main() { 65 | std::ios_base::sync_with_stdio(false); 66 | 67 | int t; 68 | std::cin >> t; 69 | for (int i = 0; i < t; ++i) 70 | testcase(); 71 | } 72 | -------------------------------------------------------------------------------- /Week10/SurveillancePhotograph/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | 13 | typedef boost::adjacency_list_traits traits; 14 | typedef boost::adjacency_list>>> graph; 18 | 19 | typedef traits::vertex_descriptor vertex_desc; 20 | typedef traits::edge_descriptor edge_desc; 21 | 22 | class edge_adder { 23 | graph &G; 24 | 25 | public: 26 | explicit edge_adder(graph &G) : G(G) {} 27 | 28 | void add_edge(int from, int to, long capacity) { 29 | auto c_map = boost::get(boost::edge_capacity, G); 30 | auto r_map = boost::get(boost::edge_reverse, G); 31 | const auto e = boost::add_edge(from, to, G).first; 32 | const auto rev_e = boost::add_edge(to, from, G).first; 33 | c_map[e] = capacity; 34 | c_map[rev_e] = 0; 35 | r_map[e] = rev_e; 36 | r_map[rev_e] = e; 37 | } 38 | }; 39 | 40 | void testcase() { 41 | int n, m, k, l; std::cin >> n >> m >> k >> l; 42 | int src = 2 * n, dst = src + 1; 43 | graph g(dst + 1); 44 | edge_adder adder(g); 45 | 46 | for (int i = 0; i < k; i++) { 47 | int x; std::cin >> x; 48 | adder.add_edge(src, x, 1); 49 | adder.add_edge(n + x, dst, 1); 50 | } 51 | 52 | for (int i = 0; i < l; i++) { 53 | int x; std::cin >> x; 54 | adder.add_edge(x, n + x, 1); 55 | } 56 | 57 | for (int i = 0; i < m; i++) { 58 | int x, y; std::cin >> x >> y; 59 | adder.add_edge(x, y, k); 60 | adder.add_edge(n + x, n + y, 1); 61 | } 62 | 63 | long flow = boost::push_relabel_max_flow(g, src, dst); 64 | std::cout << flow << std::endl; 65 | } 66 | 67 | int main() { 68 | std::ios_base::sync_with_stdio(false); 69 | 70 | int t; 71 | std::cin >> t; 72 | for (int i = 0; i < t; ++i) 73 | testcase(); 74 | } 75 | -------------------------------------------------------------------------------- /Week04/IronIslands/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | void testcase() { 11 | int n, k, w; std::cin >> n >> k >> w; 12 | std::vector c(n); 13 | std::vector> ww(w); 14 | std::unordered_map>> wwm; 15 | 16 | for (auto &i: c) 17 | std::cin >> i; 18 | 19 | for (int i = 0; i < w; i++) { 20 | int l; std::cin >> l; 21 | std::vector r(l + 1, 0); 22 | 23 | for (int j = 1; j <= l; j++) { 24 | int x; std::cin >> x; 25 | r[j] = r[j - 1] + c[x]; 26 | 27 | auto best = wwm.find(r[j]); 28 | if (best == wwm.end()) { 29 | auto v = std::vector>(2, std::make_pair(-1, -1)); 30 | v[0].first = i; 31 | v[0].second = j; 32 | wwm.insert(std::make_pair(r[j], v)); 33 | } else if (j > best->second[0].second) { 34 | best->second[1] = best->second[0]; 35 | best->second[0].first = i; 36 | best->second[0].second = j; 37 | } else if (j > best->second[1].second) { 38 | best->second[1].first = i; 39 | best->second[1].second = j; 40 | } 41 | } 42 | ww[i] = r; 43 | } 44 | 45 | int max = c[0] == k ? 1 : 0; 46 | for (int w1 = 0; w1 < w; w1++) { 47 | int i = 2, j = 2; 48 | while (j < (int)ww[w1].size()) { 49 | int err = k - (ww[w1][j] - ww[w1][i - 1]); 50 | if (err == 0) 51 | max = std::max(max, j - i + 1); 52 | 53 | if (err < 0 && i < j) 54 | i++; 55 | else 56 | j++; 57 | } 58 | 59 | for (int i = 2; i < (int)ww[w1].size(); i++) { 60 | int rest = k - (ww[w1][i] - c[0]); 61 | auto tgt = wwm.find(rest); 62 | 63 | if (tgt != wwm.end()) { 64 | int w2 = tgt->second[0].first, w3 = tgt->second[1].first; 65 | if (w1 != w2) 66 | max = std::max(max, i - 1 + tgt->second[0].second); 67 | else if (w3 != -1 && w1 != w3) 68 | max = std::max(max, i - 1 + tgt->second[1].second); 69 | } 70 | } 71 | } 72 | 73 | std::cout << max << std::endl; 74 | } 75 | 76 | int main() { 77 | std::ios_base::sync_with_stdio(false); 78 | 79 | int t; 80 | std::cin >> t; 81 | for (int i = 0; i < t; ++i) 82 | testcase(); 83 | } 84 | -------------------------------------------------------------------------------- /Week13/AugeanStables/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | typedef int IT; 14 | typedef CGAL::Gmpz ET; 15 | typedef CGAL::Quadratic_program Program; 16 | typedef CGAL::Quadratic_program_solution Solution; 17 | 18 | int n; 19 | std::vector f, c, k, l, m; 20 | 21 | bool solves(const int a, const int p) { 22 | Program lp (CGAL::LARGER, true, 0, true, 1); 23 | const int H1 = 0, H2 = 1, H3 = 2; 24 | 25 | lp.set_a(H1, n, -1); lp.set_b(n, -1); 26 | lp.set_a(H2, n + 1, -1); lp.set_b(n + 1, -1); 27 | lp.set_a(H3, n + 2, -1); lp.set_b(n + 2, -1); 28 | 29 | for (int i = 0; i < n; i++) { 30 | lp.set_a(H1, i, k[i] + a * a); 31 | lp.set_a(H2, i, l[i] + p * p); 32 | lp.set_a(H3, i, m[i] + a * p); 33 | lp.set_b(i, f[i] - c[i]); 34 | } 35 | 36 | return !CGAL::solve_nonnegative_linear_program(lp, ET()).is_infeasible(); 37 | } 38 | 39 | void testcase() { 40 | std::cin >> n; 41 | long a[25] = {0}, p[25] = {0}; 42 | f = std::vector(n); 43 | c = std::vector(n); 44 | k = std::vector(n); 45 | l = std::vector(n); 46 | m = std::vector(n); 47 | 48 | for (int i = 0; i < n; i++) { 49 | std::cin >> f[i] >> c[i] >> k[i] >> l[i] >> m[i]; 50 | } 51 | 52 | for (int i = 1; i <= 24; i++) { 53 | int x; std::cin >> x; 54 | a[i] = x + a[i - 1]; 55 | } 56 | 57 | for (int i = 1; i <= 24; i++) { 58 | int x; std::cin >> x; 59 | p[i] = x + p[i - 1]; 60 | } 61 | 62 | int best = 49; 63 | for (int at = 0; at < 25 && at <= best; at++) { 64 | int start = 0, end = std::min(25, best - at); 65 | while (start < end) { 66 | int pt = (start + end) / 2; 67 | 68 | if (solves(a[at], p[pt])) { 69 | best = at + pt; 70 | end = pt; 71 | } else 72 | start = pt + 1; 73 | } 74 | } 75 | 76 | if (best == 49) 77 | std::cout << "Impossible!" << std::endl; 78 | else 79 | std::cout << best << std::endl; 80 | } 81 | 82 | int main() { 83 | std::ios_base::sync_with_stdio(false); 84 | 85 | int t; 86 | std::cin >> t; 87 | for (int i = 0; i < t; ++i) 88 | testcase(); 89 | } 90 | -------------------------------------------------------------------------------- /Week10/Lannister/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | typedef long IT; 14 | typedef CGAL::Gmpz ET; 15 | typedef CGAL::Quadratic_program Program; 16 | typedef CGAL::Quadratic_program_solution Solution; 17 | 18 | void testcase() { 19 | Program lp (CGAL::SMALLER, false, 0, false, 0); 20 | const int B = 0, C = 1, D = 2, R = 3; 21 | 22 | long n, m, s; std::cin >> n >> m >> s; 23 | long x_sum = 0, y_sum = 0; 24 | std::vector> houses(n + m); 25 | 26 | for (int i = 0; i < n; i++) { 27 | long x, y; std::cin >> x >> y; 28 | lp.set_a(B, i, -y); lp.set_a(C, i, -1); lp.set_b(i, -x); 29 | houses[i] = {x, y}; 30 | x_sum += x; 31 | y_sum += y; 32 | } 33 | 34 | for (int i = 0; i < m; i++) { 35 | long x, y; std::cin >> x >> y; 36 | lp.set_a(B, n + i, y); lp.set_a(C, n + i, 1); lp.set_b(n + i, x); 37 | houses[n + i] = {x, y}; 38 | x_sum -= x; 39 | y_sum -= y; 40 | } 41 | 42 | Solution sol = CGAL::solve_linear_program(lp, ET()); 43 | if (sol.is_infeasible()) { 44 | std::cout << "Yuck!" << std::endl; 45 | return; 46 | } 47 | 48 | if (s != -1) { 49 | lp.set_a(B, n + m, y_sum); 50 | lp.set_a(C, n + m, n - m); 51 | lp.set_b(n + m, s + x_sum); 52 | 53 | Solution sol = CGAL::solve_linear_program(lp, ET()); 54 | if (sol.is_infeasible()) { 55 | std::cout << "Bankrupt!" << std::endl; 56 | return; 57 | } 58 | } 59 | 60 | int start = n + m + 1; 61 | for (int i = 0; i < n + m; i++) { 62 | long x = houses[i].first, y = houses[i].second; 63 | lp.set_a(B, start + 2*i, -x); 64 | lp.set_a(D, start + 2*i, 1); 65 | lp.set_a(R, start + 2*i, -1); 66 | lp.set_b(start + 2*i, y); 67 | 68 | lp.set_a(B, start + 2*i + 1, x); 69 | lp.set_a(D, start + 2*i + 1, -1); 70 | lp.set_a(R, start + 2*i + 1, -1); 71 | lp.set_b(start + 2*i + 1, -y); 72 | } 73 | 74 | lp.set_c(R, 1); 75 | sol = CGAL::solve_linear_program(lp, ET()); 76 | std::cout << (long)std::ceil(CGAL::to_double(sol.objective_value())) << std::endl; 77 | } 78 | 79 | int main() { 80 | std::ios_base::sync_with_stdio(false); 81 | 82 | int t; 83 | std::cin >> t; 84 | for (int i = 0; i < t; ++i) 85 | testcase(); 86 | } 87 | -------------------------------------------------------------------------------- /Week05/SeverusSnape/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using AP = std::vector>; 10 | using MEMO = std::vector>>; 11 | 12 | void fill_dp(AP& a_pots, MEMO& m, int H, int n) { 13 | for (int i = 0; i < n; i++) 14 | for (int j = 1, sum = 0; j <= n; j++) { 15 | if (i + j - 1 < n) 16 | sum += a_pots[i + j - 1].first; 17 | 18 | m[i][H][j] = sum; 19 | } 20 | 21 | for (int i = n - 1; i >= 0; i--) 22 | for (int h = H - 1; h >= 0; h--) 23 | for (int j = 1; j <= n; j++) { 24 | int new_h = std::min(H, h + (int)a_pots[i].second); 25 | long take = m[i + 1][new_h][j - 1], leave = m[i + 1][h][j]; 26 | 27 | if (take != 0 || new_h == H) 28 | take += a_pots[i].first; 29 | 30 | m[i][h][j] = std::max(take, leave); 31 | } 32 | } 33 | 34 | void testcase() { 35 | long n, m, a, b, P, H, W; std::cin >> n >> m >> a >> b >> P >> H >> W; 36 | MEMO memo(n + 1, std::vector>(H + 1, std::vector(n + 1, 0))); 37 | std::vector> a_pots(n); 38 | std::vector b_pots(m); 39 | 40 | for (int i = 0; i < n; i++) { 41 | int p, h; std::cin >> p >> h; 42 | a_pots[i] = std::make_pair(p, h); 43 | } 44 | 45 | for (int i = 0; i < m; i++) 46 | std::cin >> b_pots[i]; 47 | 48 | std::sort(b_pots.begin(), b_pots.end(), std::greater()); 49 | 50 | int start_idx = b_pots[0] >= W ? 0 : m; 51 | for (int i = 1; i < m; i++) { 52 | b_pots[i] += b_pots[i - 1]; 53 | 54 | if (start_idx == m && b_pots[i] >= W) 55 | start_idx = i; 56 | } 57 | 58 | if (start_idx == m) { 59 | std::cout << "-1" << std::endl; 60 | return; 61 | } 62 | 63 | std::sort(a_pots.begin(), a_pots.end(), std::greater>()); 64 | fill_dp(a_pots, memo, H, n); 65 | 66 | for (int i = start_idx; i < m; i++) { 67 | int max_pots = a == 0 ? n : (b_pots[i] - W) / a; 68 | 69 | for (long j = 0; j <= max_pots; j++) 70 | if (memo[0][0][j] >= P + (i + 1) * b) { 71 | std::cout << (i + j + 1) << std::endl; 72 | return; 73 | } 74 | } 75 | 76 | std::cout << "-1" << std::endl; 77 | } 78 | 79 | int main() { 80 | std::ios_base::sync_with_stdio(false); 81 | 82 | int t; 83 | std::cin >> t; 84 | for (int i = 0; i < t; ++i) 85 | testcase(); 86 | } 87 | -------------------------------------------------------------------------------- /PreviousYears/2022/EmpireStrikesBack/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | typedef CGAL::Exact_predicates_inexact_constructions_kernel K; 13 | typedef CGAL::Delaunay_triangulation_2 Triangulation; 14 | typedef Triangulation::Edge_iterator Edge_iterator; 15 | typedef K::Point_2 P; 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | typedef CGAL::Gmpq IT; 22 | typedef CGAL::Gmpq ET; 23 | 24 | typedef CGAL::Quadratic_program Program; 25 | typedef CGAL::Quadratic_program_solution Solution; 26 | 27 | void testcase() { 28 | int a, s, b, e; std::cin >> a >> s >> b >> e; 29 | Program lp (CGAL::LARGER, true, 0, false, 0); 30 | std::vector

particles(a), shots(s), hunters(b); 31 | std::vector densities(a); 32 | std::vector max_radius(s, std::numeric_limits::max()); 33 | 34 | for (int i = 0; i < a; i++) { 35 | int x, y; std::cin >> x >> y >> densities[i]; 36 | particles[i] = P(x, y); 37 | } 38 | 39 | for (int i = 0; i < s; i++) { 40 | int x, y; std::cin >> x >> y; 41 | shots[i] = P(x, y); 42 | } 43 | 44 | for (int i = 0; i < b; i++) { 45 | int x, y; std::cin >> x >> y; 46 | hunters[i] = P(x, y); 47 | } 48 | 49 | Triangulation t; 50 | t.insert(hunters.begin(), hunters.end()); 51 | 52 | for (int i = 0; i < s && b != 0; i++) { 53 | P closest = t.nearest_vertex(shots[i])->point(); 54 | max_radius[i] = CGAL::squared_distance(shots[i], closest); 55 | } 56 | 57 | for (int i = 0; i < a; i++) { 58 | for (int j = 0; j < s; j++) { 59 | K::FT dist = CGAL::squared_distance(particles[i], shots[j]); 60 | if (dist > max_radius[j]) 61 | continue; 62 | 63 | lp.set_a(j, i, IT(1, std::max(K::FT(1), dist))); 64 | } 65 | 66 | lp.set_b(i, IT(densities[i])); 67 | } 68 | 69 | for (int j = 0; j < s; j++) { 70 | lp.set_a(j, a, IT(-1)); 71 | } 72 | lp.set_b(a, IT(-e)); 73 | 74 | Solution sol = CGAL::solve_linear_program(lp, ET()); 75 | std::cout << (sol.is_infeasible() ? "n" : "y") << std::endl; 76 | } 77 | 78 | int main() { 79 | std::ios_base::sync_with_stdio(false); 80 | 81 | int t; 82 | std::cin >> t; 83 | for (int i = 0; i < t; ++i) 84 | testcase(); 85 | } 86 | -------------------------------------------------------------------------------- /Week08/Suez/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | using IT = int; 14 | using ET = CGAL::Gmpz; 15 | using Program = CGAL::Quadratic_program; 16 | using Solution = CGAL::Quadratic_program_solution; 17 | 18 | void testcase() { 19 | int n, m, h, w; std::cin >> n >> m >> h >> w; 20 | double ar = (double)h / w; 21 | 22 | Program lp(CGAL::SMALLER, true, 1, false, 0); 23 | std::vector> free(n); 24 | std::vector> old(m); 25 | 26 | for (int i = 0; i < n; i++) { 27 | int x, y; std::cin >> x >> y; 28 | free[i] = std::make_pair(x, y); 29 | } 30 | 31 | for (int i = 0; i < m; i++) { 32 | int x, y; std::cin >> x >> y; 33 | old[i] = std::make_pair(x, y); 34 | } 35 | 36 | for (int i = 0; i < n; i++) { 37 | int xa = free[i].first, ya = free[i].second; 38 | 39 | for (int j = i + 1; j < n; j++) { 40 | int xb = free[j].first, yb = free[j].second; 41 | int dx = std::abs(xb - xa), dy = std::abs(yb - ya); 42 | int idx = i*n + j; 43 | 44 | if (dx == 0 || (dy != 0 && ((double)dy / dx) >= ar)) { 45 | lp.set_a(i, idx, h); 46 | lp.set_a(j, idx, h); 47 | lp.set_b(idx, 2 * dy); 48 | } else { 49 | lp.set_a(i, idx, w); 50 | lp.set_a(j, idx, w); 51 | lp.set_b(idx, 2 * dx); 52 | } 53 | } 54 | 55 | double best = std::numeric_limits::max(); 56 | for (int j = 0; j < m; j++) { 57 | int xb = old[j].first, yb = old[j].second; 58 | int dx = std::abs(xb - xa), dy = std::abs(yb - ya); 59 | 60 | if (dx == 0 || (dy != 0 && ((double)dy / dx) >= ar)) { 61 | if (2 *(double)dy / h < best) { 62 | best = 2 * (double)dy / h; 63 | lp.set_a(i, n*n + i, h); 64 | lp.set_b(n*n + i, 2*dy - h); 65 | } 66 | } else { 67 | if (2 * (double)dx / w < best) { 68 | best = 2 * (double)dx / w; 69 | lp.set_a(i, n*n + i, w); 70 | lp.set_b(n*n + i, 2*dx - w); 71 | } 72 | } 73 | } 74 | 75 | lp.set_c(i, -2 * (h + w)); 76 | } 77 | 78 | Solution s = CGAL::solve_linear_program(lp, ET()); 79 | std::cout << (long)std::ceil(-CGAL::to_double(s.objective_value())) << std::endl; 80 | } 81 | 82 | int main() { 83 | std::ios_base::sync_with_stdio(false); 84 | 85 | int t; 86 | std::cin >> t; 87 | for (int i = 0; i < t; ++i) 88 | testcase(); 89 | } 90 | -------------------------------------------------------------------------------- /Week08/KingdomDefence/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | // BGL include 10 | #include 11 | 12 | // BGL flow include *NEW* 13 | #include 14 | 15 | // Graph Type with nested interior edge properties for flow algorithms 16 | typedef boost::adjacency_list_traits traits; 17 | typedef boost::adjacency_list>>> graph; 21 | 22 | typedef traits::vertex_descriptor vertex_desc; 23 | typedef traits::edge_descriptor edge_desc; 24 | 25 | // Custom edge adder class, highly recommended 26 | class edge_adder { 27 | graph &G; 28 | 29 | public: 30 | explicit edge_adder(graph &G) : G(G) {} 31 | 32 | void add_edge(int from, int to, long capacity) { 33 | auto c_map = boost::get(boost::edge_capacity, G); 34 | auto r_map = boost::get(boost::edge_reverse, G); 35 | const auto e = boost::add_edge(from, to, G).first; 36 | const auto rev_e = boost::add_edge(to, from, G).first; 37 | c_map[e] = capacity; 38 | c_map[rev_e] = 0; // reverse edge has no capacity! 39 | r_map[e] = rev_e; 40 | r_map[rev_e] = e; 41 | } 42 | }; 43 | 44 | void testcase() { 45 | int l, p; std::cin >> l >> p; 46 | int src = l, dst = l + 1; 47 | graph g(l + 2); 48 | edge_adder adder(g); 49 | std::vector supply(l, 0); 50 | 51 | for (int i = 0; i < l; i++) { 52 | int g, d; std::cin >> g >> d; 53 | supply[i] = g - d; 54 | } 55 | 56 | for (int i = 0; i < p; i++) { 57 | int f, t, min, max; std::cin >> f >> t >> min >> max; 58 | supply[f] -= min; 59 | supply[t] += min; 60 | adder.add_edge(f, t, max - min); 61 | } 62 | 63 | int tot = 0; 64 | for (int i = 0; i < l; i++) { 65 | if (supply[i] > 0) 66 | adder.add_edge(src, i, supply[i]); 67 | else { 68 | tot -= supply[i]; 69 | adder.add_edge(i, dst, -supply[i]); 70 | } 71 | } 72 | 73 | long flow = boost::push_relabel_max_flow(g, src, dst); 74 | std::cout << ((flow == tot) ? "yes" : "no") << std::endl; 75 | } 76 | 77 | int main() { 78 | std::ios_base::sync_with_stdio(false); 79 | 80 | int t; 81 | std::cin >> t; 82 | for (int i = 0; i < t; ++i) 83 | testcase(); 84 | } 85 | -------------------------------------------------------------------------------- /Week04/HikingMaps/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | using K = CGAL::Exact_predicates_inexact_constructions_kernel; 12 | using P = K::Point_2; 13 | using S = K::Segment_2; 14 | using L = K::Line_2; 15 | using T = K::Triangle_2; 16 | 17 | void testcase() { 18 | int m, n; std::cin >> m >> n; 19 | std::vector legs(m - 1); 20 | std::vector> fragments(n, std::vector

(6)); 21 | std::vector> coverages(n + 1, std::vector(m - 1, 0)); 22 | 23 | int x, y; std::cin >> x >> y; 24 | P prev(x, y); 25 | for (int i = 0; i < m - 1; i++) { 26 | int x, y; std::cin >> x >> y; 27 | P next(x, y); 28 | 29 | legs[i] = S(prev, next); 30 | prev = next; 31 | } 32 | 33 | for (int i = 0; i < n; i++) { 34 | int x11, y11, x12, y12; std::cin >> x11 >> y11 >> x12 >> y12; 35 | int x21, y21, x22, y22; std::cin >> x21 >> y21 >> x22 >> y22; 36 | int x31, y31, x32, y32; std::cin >> x31 >> y31 >> x32 >> y32; 37 | P p1(x11, y11), p2(x12, y12), p3(x21, y21), p4(x22, y22), p5(x31, y31), p6(x32, y32); 38 | 39 | if (CGAL::right_turn(p1, p2, p3)) 40 | std::swap(p1, p2); 41 | 42 | if (CGAL::right_turn(p3, p4, p5)) 43 | std::swap(p3, p4); 44 | 45 | if (CGAL::right_turn(p5, p6, p1)) 46 | std::swap(p5, p6); 47 | 48 | fragments[i] = std::vector

({p1, p2, p3, p4, p5, p6}); 49 | } 50 | 51 | for (int i = 1; i <= n; i++) { 52 | for (int j = 0; j < m - 1; j++) { 53 | coverages[i][j] = coverages[i - 1][j] + 1; 54 | 55 | for (int side = 0; side < 3; side++) { 56 | P p1 = fragments[i - 1][side * 2], p2 = fragments[i - 1][side * 2 + 1]; 57 | 58 | if (CGAL::right_turn(p1, p2, legs[j].start()) 59 | || CGAL::right_turn(p1, p2, legs[j].end())) 60 | { 61 | coverages[i][j]--; 62 | break; 63 | } 64 | } 65 | } 66 | } 67 | 68 | int start = 0, end = 1, best = n; 69 | while (end <= n && start <= end) { 70 | bool covers = true; 71 | for (int j = 0; j < m - 1 && covers; j++) 72 | covers = (coverages[end][j] - coverages[start][j]) >= 1; 73 | 74 | if (covers && end - start < best) 75 | best = end - start; 76 | 77 | if (covers) 78 | start++; 79 | else 80 | end++; 81 | } 82 | 83 | std::cout << best << std::endl; 84 | } 85 | 86 | int main() { 87 | std::ios_base::sync_with_stdio(false); 88 | 89 | int t; 90 | std::cin >> t; 91 | for (int i = 0; i < t; ++i) 92 | testcase(); 93 | } 94 | -------------------------------------------------------------------------------- /PreviousYears/2022/FleetRace/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | typedef boost::adjacency_list_traits traits; 16 | typedef boost::adjacency_list > > > > graph; 21 | 22 | typedef boost::graph_traits::edge_descriptor edge_desc; 23 | typedef boost::graph_traits::out_edge_iterator out_edge_it; 24 | 25 | class edge_adder { 26 | graph &G; 27 | 28 | public: 29 | explicit edge_adder(graph &G) : G(G) {} 30 | void add_edge(int from, int to, long capacity, long cost) { 31 | auto c_map = boost::get(boost::edge_capacity, G); 32 | auto r_map = boost::get(boost::edge_reverse, G); 33 | auto w_map = boost::get(boost::edge_weight, G); 34 | const edge_desc e = boost::add_edge(from, to, G).first; 35 | const edge_desc rev_e = boost::add_edge(to, from, G).first; 36 | c_map[e] = capacity; 37 | c_map[rev_e] = 0; 38 | r_map[e] = rev_e; 39 | r_map[rev_e] = e; 40 | w_map[e] = cost; 41 | w_map[rev_e] = -cost; 42 | } 43 | }; 44 | 45 | void testcase() { 46 | int b, s, p; std::cin >> b >> s >> p; 47 | int src = b + s, snk = src + 1; 48 | graph g(snk + 1); 49 | edge_adder adder(g); 50 | 51 | for (int i = 0; i < b; i++) { 52 | adder.add_edge(src, i, 1, 0); 53 | adder.add_edge(i, snk, 1, 50); 54 | } 55 | 56 | for (int i = b; i < b + s; i++) { 57 | adder.add_edge(i, snk, 1, 0); 58 | } 59 | 60 | for (int i = 0; i < p; i++) { 61 | int bi, si, ci; std::cin >> bi >> si >> ci; 62 | adder.add_edge(bi, b + si, 1, 50 - ci); 63 | } 64 | 65 | boost::successive_shortest_path_nonnegative_weights(g, src, snk); 66 | int cost = boost::find_flow_cost(g); 67 | 68 | std::cout << (50*b - cost) << std::endl; 69 | } 70 | 71 | int main() { 72 | std::ios_base::sync_with_stdio(false); 73 | 74 | int t; 75 | std::cin >> t; 76 | for (int i = 0; i < t; ++i) 77 | testcase(); 78 | } 79 | -------------------------------------------------------------------------------- /Week06/Knights/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | // Graph Type with nested interior edge properties for flow algorithms 13 | typedef boost::adjacency_list_traits traits; 14 | typedef boost::adjacency_list>>> graph; 18 | 19 | typedef traits::vertex_descriptor vertex_desc; 20 | typedef traits::edge_descriptor edge_desc; 21 | 22 | // Custom edge adder class, highly recommended 23 | class edge_adder { 24 | graph &G; 25 | 26 | public: 27 | explicit edge_adder(graph &G) : G(G) {} 28 | 29 | void add_edge(int from, int to, long capacity) { 30 | auto c_map = boost::get(boost::edge_capacity, G); 31 | auto r_map = boost::get(boost::edge_reverse, G); 32 | const auto e = boost::add_edge(from, to, G).first; 33 | const auto rev_e = boost::add_edge(to, from, G).first; 34 | c_map[e] = capacity; 35 | c_map[rev_e] = 0; // reverse edge has no capacity! 36 | r_map[e] = rev_e; 37 | r_map[rev_e] = e; 38 | } 39 | }; 40 | 41 | void testcase() { 42 | int m, n, k, c; std::cin >> m >> n >> k >> c; 43 | const int src = 2 * n * m, dst = src + 1; 44 | graph g(dst + 1); 45 | edge_adder adder(g); 46 | 47 | for (int i = 0; i < n; i++) 48 | for (int j = 0; j < m; j++) { 49 | int in = i * m + j, out = in + n * m; 50 | 51 | adder.add_edge(in, out, c); 52 | 53 | if (i != 0) 54 | adder.add_edge(out, in - m, 1); 55 | else 56 | adder.add_edge(out, dst, 1); 57 | 58 | if (i != n - 1) 59 | adder.add_edge(out, in + m, 1); 60 | else 61 | adder.add_edge(out, dst, 1); 62 | 63 | if (j != 0) 64 | adder.add_edge(out, in - 1, 1); 65 | else 66 | adder.add_edge(out, dst, 1); 67 | 68 | if (j != m - 1) 69 | adder.add_edge(out, in + 1, 1); 70 | else 71 | adder.add_edge(out, dst, 1); 72 | } 73 | 74 | for (int i = 0; i < k; i++) { 75 | int x, y; std::cin >> x >> y; 76 | int in = y * m + x; 77 | adder.add_edge(src, in, 1); 78 | } 79 | 80 | long flow = boost::push_relabel_max_flow(g, src, dst); 81 | std::cout << flow << std::endl; 82 | } 83 | 84 | int main() { 85 | std::ios_base::sync_with_stdio(false); 86 | 87 | int t; 88 | std::cin >> t; 89 | for (int i = 0; i < t; ++i) 90 | testcase(); 91 | } 92 | -------------------------------------------------------------------------------- /Week10/RubeusHagrid/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | typedef boost::adjacency_list 14 | > graph; 15 | typedef boost::property_map::type weight_map; 16 | typedef boost::graph_traits::edge_descriptor edge_desc; 17 | typedef boost::graph_traits::edge_iterator edge_it; 18 | typedef boost::graph_traits::out_edge_iterator out_edge_it; 19 | 20 | std::vector galleons, weights, counts; 21 | 22 | void fill_stats(graph& g, const int src) { 23 | weight_map weight_map = boost::get(boost::edge_weight, g); 24 | 25 | out_edge_it oe_beg, oe_end; 26 | for (boost::tie(oe_beg, oe_end) = boost::out_edges(src, g); oe_beg != oe_end; ++oe_beg) { 27 | int tgt = boost::target(*oe_beg, g); 28 | fill_stats(g, tgt); 29 | 30 | weights[src] += weight_map[*oe_beg] + weights[tgt]; 31 | counts[src] += counts[tgt]; 32 | } 33 | } 34 | 35 | long solve(graph& g, const int src, long time) { 36 | weight_map weight_map = boost::get(boost::edge_weight, g); 37 | std::vector> children; 38 | 39 | out_edge_it oe_beg, oe_end; 40 | for (boost::tie(oe_beg, oe_end) = boost::out_edges(src, g); oe_beg != oe_end; ++oe_beg) 41 | children.push_back({boost::target(*oe_beg, g), weight_map[*oe_beg]}); 42 | 43 | std::sort(children.begin(), children.end(), 44 | [](const std::pair& e1, const std::pair& e2) -> bool { 45 | auto [tgt1, w1] = e1; 46 | auto [tgt2, w2] = e2; 47 | 48 | return (w1 + weights[tgt1]) * counts[tgt2] < (w2 + weights[tgt2]) * counts[tgt1]; 49 | } 50 | ); 51 | 52 | long sum = galleons[src] - time; 53 | for (const auto [tgt, weight]: children) { 54 | sum += solve(g, tgt, time + weight); 55 | time += 2 * (weight + weights[tgt]); 56 | } 57 | 58 | return sum; 59 | } 60 | 61 | void testcase() { 62 | int n; std::cin >> n; 63 | graph g(n + 1); 64 | galleons = std::vector(n + 1, 0); 65 | weights = std::vector(n + 1, 0); 66 | counts = std::vector(n + 1, 1); 67 | 68 | for (int i = 1; i <= n; i++) 69 | std::cin >> galleons[i]; 70 | 71 | for (int i = 0; i < n; i++) { 72 | int u, v, l; std::cin >> u >> v >> l; 73 | boost::add_edge(u, v, l, g); 74 | } 75 | 76 | fill_stats(g, 0); 77 | std::cout << solve(g, 0, 0) << std::endl; 78 | } 79 | 80 | int main() { 81 | std::ios_base::sync_with_stdio(false); 82 | 83 | int t; 84 | std::cin >> t; 85 | for (int i = 0; i < t; ++i) 86 | testcase(); 87 | } 88 | -------------------------------------------------------------------------------- /Week06/Tiles/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | // Graph Type with nested interior edge properties for flow algorithms 13 | typedef boost::adjacency_list_traits traits; 14 | typedef boost::adjacency_list>>> graph; 18 | 19 | typedef traits::vertex_descriptor vertex_desc; 20 | typedef traits::edge_descriptor edge_desc; 21 | 22 | // Custom edge adder class, highly recommended 23 | class edge_adder { 24 | graph &G; 25 | 26 | public: 27 | explicit edge_adder(graph &G) : G(G) {} 28 | 29 | void add_edge(int from, int to, long capacity) { 30 | auto c_map = boost::get(boost::edge_capacity, G); 31 | auto r_map = boost::get(boost::edge_reverse, G); 32 | const auto e = boost::add_edge(from, to, G).first; 33 | const auto rev_e = boost::add_edge(to, from, G).first; 34 | c_map[e] = capacity; 35 | c_map[rev_e] = 0; // reverse edge has no capacity! 36 | r_map[e] = rev_e; 37 | r_map[rev_e] = e; 38 | } 39 | }; 40 | 41 | void testcase() { 42 | int w, h; std::cin >> w >> h; 43 | int src = 2*w*h, dst = 2*w*h + 1; 44 | long d = 0; 45 | std::vector> garden(h, std::vector(w, false)); 46 | graph g(2*w*h + 2); 47 | edge_adder adder(g); 48 | 49 | for (int i = 0; i < h; i++) 50 | for (int j = 0; j < w; j++) { 51 | char x; std::cin >> x; 52 | int idx1 = i * w + j, idx2 = w * h + i * w + j; 53 | 54 | if (x == 'x') 55 | continue; 56 | 57 | garden[i][j] = true; 58 | d++; 59 | adder.add_edge(src, idx1, 1); 60 | adder.add_edge(idx2, dst, 1); 61 | 62 | if (i > 0 && garden[i - 1][j]) { 63 | adder.add_edge((i - 1) * w + j, idx2, 1); 64 | adder.add_edge(idx1, h * w + (i - 1) * w + j, 1); 65 | } 66 | if (j > 0 && garden[i][j - 1]) { 67 | adder.add_edge(i * w + j - 1, idx2, 1); 68 | adder.add_edge(idx1, h * w +i * w + j - 1, 1); 69 | } 70 | } 71 | 72 | if (d % 2) { 73 | std::cout << "no" << std::endl; 74 | return; 75 | } 76 | 77 | long flow = boost::push_relabel_max_flow(g, src, dst); 78 | std::cout << ((flow == d) ? "yes" : "no") << std::endl; 79 | } 80 | 81 | int main() { 82 | std::ios_base::sync_with_stdio(false); 83 | 84 | int t; 85 | std::cin >> t; 86 | for (int i = 0; i < t; ++i) 87 | testcase(); 88 | } 89 | -------------------------------------------------------------------------------- /Week07/H1N1/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | using K = CGAL::Exact_predicates_inexact_constructions_kernel; 15 | using P = K::Point_2; 16 | using Vb = CGAL::Triangulation_vertex_base_2; 17 | using Fb = CGAL::Triangulation_face_base_with_info_2, K>; 18 | using Tds = CGAL::Triangulation_data_structure_2; 19 | using Triangulation = CGAL::Delaunay_triangulation_2; 20 | using FH = Triangulation::Face_handle; 21 | 22 | void testcase(int n) { 23 | Triangulation t; 24 | std::vector

points(n); 25 | std::priority_queue> q; 26 | 27 | for (int i = 0; i < n; i++) { 28 | long x, y; std::cin >> x >> y; 29 | points[i] = P(x, y); 30 | } 31 | 32 | t.insert(points.begin(), points.end()); 33 | 34 | for (auto f = t.finite_faces_begin(); f != t.finite_faces_end(); f++) { 35 | f->info() = std::make_pair(false, 0); 36 | 37 | for (int i = 0; i < 3; i++) 38 | if (t.is_infinite(f->neighbor(i))) { 39 | auto edge_len = t.segment(f, i).squared_length(); 40 | 41 | f->info().second = std::max(f->info().second, edge_len); 42 | q.push(std::make_pair(edge_len, f)); 43 | } 44 | } 45 | 46 | while (!q.empty()) { 47 | auto curr = q.top(); 48 | q.pop(); 49 | 50 | if (!curr.second->info().first) { 51 | for (int i = 0; i < 3; i++) { 52 | auto neighbor = curr.second->neighbor(i); 53 | auto capacity = std::min(t.segment(curr.second, i).squared_length(), curr.second->info().second); 54 | 55 | if (!t.is_infinite(neighbor) && !neighbor->info().first) { 56 | neighbor->info().second = std::max(neighbor->info().second, capacity); 57 | q.push(std::make_pair(neighbor->info().second, neighbor)); 58 | } 59 | } 60 | 61 | curr.second->info().first = true; 62 | } 63 | } 64 | 65 | int m; std::cin >> m; 66 | for (int i = 0; i < m; i++) { 67 | long x, y, d; std::cin >> x >> y >> d; 68 | P p(x, y); 69 | 70 | if (d > std::ceil(CGAL::squared_distance(p, t.nearest_vertex(p)->point()))) 71 | std::cout << "n"; 72 | else { 73 | FH fh = t.locate(p); 74 | 75 | if (t.is_infinite(fh)) 76 | std::cout << "y"; 77 | else 78 | std::cout << ((std::floor(fh->info().second) >= 4 * d) ? "y" : "n"); 79 | } 80 | } 81 | 82 | std::cout << std::endl; 83 | } 84 | 85 | int main() 86 | { 87 | std::ios_base::sync_with_stdio(false); 88 | 89 | int n; std::cin >> n; 90 | while (n) { 91 | testcase(n); 92 | std::cin >> n; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /Week12/ReturnOfTheJedi/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | typedef boost::adjacency_list 15 | > graph; 16 | typedef boost::property_map::type weight_map; 17 | typedef boost::graph_traits::edge_descriptor edge_desc; 18 | 19 | int n, tatooine; 20 | std::vector> max_dists, weights, mst_adj; 21 | std::vector> in_mst; 22 | std::vector pred; 23 | std::vector visited; 24 | 25 | void fill_dists(const int root, const int curr, int max) { 26 | max_dists[root][curr] = max_dists[curr][root] = max; 27 | visited[curr] = true; 28 | 29 | for (const int next: mst_adj[curr]) { 30 | if (!visited[next]) 31 | fill_dists(root, next, std::max(max, weights[curr][next])); 32 | } 33 | } 34 | 35 | void testcase() { 36 | std::cin >> n >> tatooine; 37 | graph g(n); 38 | 39 | max_dists = std::vector>(n, std::vector(n)); 40 | weights = std::vector>(n, std::vector(n)); 41 | mst_adj = std::vector>(n, std::vector()); 42 | in_mst = std::vector>(n, std::vector(n, false)); 43 | pred = std::vector(n); 44 | 45 | for (int i = 0; i < n; i++) { 46 | for (int j = i + 1; j < n; j++) { 47 | int c; std::cin >> c; 48 | boost::add_edge(i, j, c, g); 49 | weights[i][j] = weights[j][i] = c; 50 | } 51 | } 52 | 53 | boost::prim_minimum_spanning_tree( 54 | g, 55 | boost::make_iterator_property_map(pred.begin(), boost::get(boost::vertex_index, g)), 56 | boost::root_vertex(tatooine - 1) 57 | ); 58 | 59 | long cost = 0; 60 | for (int i = 0; i < n; i++) { 61 | if (i != pred[i]) { 62 | mst_adj[i].push_back(pred[i]); 63 | mst_adj[pred[i]].push_back(i); 64 | in_mst[i][pred[i]] = in_mst[pred[i]][i] = true; 65 | cost += weights[i][pred[i]]; 66 | } 67 | } 68 | 69 | for (int i = 0; i < n; i++) { 70 | visited = std::vector(n, false); 71 | fill_dists(i, i, -1); 72 | } 73 | 74 | int best = std::numeric_limits::max(); 75 | for (int i = 0; i < n; i++) { 76 | for (int j = i + 1; j < n; j++) { 77 | if (!in_mst[i][j]) 78 | best = std::min(best, weights[i][j] - max_dists[i][j]); 79 | } 80 | } 81 | 82 | std::cout << cost + best << std::endl; 83 | } 84 | 85 | int main() { 86 | std::ios_base::sync_with_stdio(false); 87 | 88 | int t; 89 | std::cin >> t; 90 | for (int i = 0; i < t; ++i) 91 | testcase(); 92 | } 93 | -------------------------------------------------------------------------------- /Week05/AsterixTheGaul/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | bool reaches(const std::vector>& mov, const int s, const long D, const long T) { 11 | int n = (int) mov.size(), s1 = n / 2, s2 = n - s1; 12 | std::vector> l2; 13 | l2.reserve(1 << s2); 14 | 15 | for (int idx = 1; idx < (1 << s2); idx++) { 16 | long t = 0, d = 0; 17 | for (int i = 0; i < n; i++) { 18 | if (idx & (1 << i)) { 19 | t += mov[i + s1].first; 20 | d += mov[i + s1].second + s; 21 | } 22 | 23 | if (t >= T) 24 | continue; 25 | if (d >= D) 26 | return true; 27 | } 28 | 29 | l2.push_back(std::make_pair(t, d)); 30 | } 31 | 32 | std::sort(l2.begin(), l2.end()); 33 | 34 | std::vector> x2; 35 | x2.reserve(l2.size()); 36 | x2.push_back(*l2.begin()); 37 | for (std::size_t i = 1; i < l2.size(); i++) 38 | if (l2[i].second > (x2.end() - 1)->second) 39 | x2.push_back(l2[i]); 40 | 41 | for (int idx = 1; idx < (1 << s1); idx++) { 42 | long t = 0, d = 0; 43 | for (int i = 0; i < n; i++) { 44 | if (idx & (1 << i)) { 45 | t += mov[i].first; 46 | d += mov[i].second + s; 47 | } 48 | 49 | if (t >= T) 50 | continue; 51 | if (d >= D) 52 | return true; 53 | } 54 | 55 | int start = 0, end = x2.size() - 1, boundary = 0; 56 | while (start <= end) { 57 | int mid = (start + end) / 2; 58 | 59 | if (t + x2[mid].first < T) { 60 | boundary = mid; 61 | start = mid + 1; 62 | } else 63 | end = mid - 1; 64 | } 65 | 66 | auto val = x2[boundary]; 67 | if (t + val.first < T && d + val.second >= D) 68 | return true; 69 | } 70 | 71 | return false; 72 | } 73 | 74 | void testcase() { 75 | int n, m; long D, T; std::cin >> n >> m >> D >> T; 76 | std::vector> mov(n); 77 | std::vector s(m + 1, 0); 78 | 79 | for (int i = 0; i < n; i++) { 80 | int d, t; std::cin >> d >> t; 81 | mov[i] = std::make_pair(t, d); 82 | } 83 | 84 | for (int i = 1; i <= m; i++) 85 | std::cin >> s[i]; 86 | 87 | int start = 0, end = m, boundary = -1; 88 | while (start <= end) { 89 | int mid = (start + end) / 2; 90 | 91 | if (reaches(mov, s[mid], D, T)) { 92 | boundary = mid; 93 | end = mid - 1; 94 | } else 95 | start = mid + 1; 96 | } 97 | 98 | if (boundary == -1) 99 | std::cout << "Panoramix captured" << std::endl; 100 | else 101 | std::cout << boundary << std::endl; 102 | 103 | } 104 | 105 | int main() { 106 | std::ios_base::sync_with_stdio(false); 107 | 108 | int t; 109 | std::cin >> t; 110 | for (int i = 0; i < t; ++i) 111 | testcase(); 112 | } 113 | -------------------------------------------------------------------------------- /Week11/India/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | typedef boost::adjacency_list_traits traits; 17 | typedef boost::adjacency_list > > > > graph; 22 | 23 | typedef boost::graph_traits::edge_descriptor edge_desc; 24 | typedef boost::graph_traits::out_edge_iterator out_edge_it; // Iterator 25 | 26 | class edge_adder { 27 | graph &G; 28 | 29 | public: 30 | explicit edge_adder(graph &G) : G(G) {} 31 | edge_desc add_edge(int from, int to, long capacity, long cost) { 32 | auto c_map = boost::get(boost::edge_capacity, G); 33 | auto r_map = boost::get(boost::edge_reverse, G); 34 | auto w_map = boost::get(boost::edge_weight, G); 35 | const edge_desc e = boost::add_edge(from, to, G).first; 36 | const edge_desc rev_e = boost::add_edge(to, from, G).first; 37 | c_map[e] = capacity; 38 | c_map[rev_e] = 0; 39 | r_map[e] = rev_e; 40 | r_map[rev_e] = e; 41 | w_map[e] = cost; 42 | w_map[rev_e] = -cost; 43 | 44 | return e; 45 | } 46 | }; 47 | 48 | void testcase() { 49 | int c, g, b, k, a; std::cin >> c >> g >> b >> k >> a; 50 | int src = c, dst = src + 1; 51 | graph G(dst + 1); 52 | edge_adder adder(G); 53 | 54 | auto c_map = boost::get(boost::edge_capacity, G); 55 | auto rc_map = boost::get(boost::edge_residual_capacity, G); 56 | auto in = adder.add_edge(src, k, 0, 0); 57 | 58 | for (int i = 0; i < g; i++) { 59 | int x, y, d, e; std::cin >> x >> y >> d >> e; 60 | adder.add_edge(x, y, e, d); 61 | } 62 | 63 | int start = 0, end = b + 1; 64 | while (start < end) { 65 | int mid = start + (end - start) / 2; 66 | 67 | c_map[in] = mid; 68 | boost::successive_shortest_path_nonnegative_weights(G, src, a); 69 | long flow = c_map[in] - rc_map[in], cost = boost::find_flow_cost(G); 70 | 71 | if (flow == mid && cost <= b) 72 | start = mid + 1; 73 | else 74 | end = mid; 75 | } 76 | 77 | std::cout << start - 1 << std::endl; 78 | } 79 | 80 | int main() { 81 | std::ios_base::sync_with_stdio(false); 82 | 83 | int t; 84 | std::cin >> t; 85 | for (int i = 0; i < t; ++i) 86 | testcase(); 87 | } 88 | -------------------------------------------------------------------------------- /Week13/CasinoRoyale/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | typedef boost::adjacency_list_traits traits; 14 | typedef boost::adjacency_list > > > > graph; // new! weightmap corresponds to costs 19 | 20 | typedef boost::graph_traits::edge_descriptor edge_desc; 21 | typedef boost::graph_traits::out_edge_iterator out_edge_it; // Iterator 22 | 23 | class edge_adder { 24 | graph &G; 25 | 26 | public: 27 | explicit edge_adder(graph &G) : G(G) {} 28 | void add_edge(int from, int to, long capacity, long cost) { 29 | auto c_map = boost::get(boost::edge_capacity, G); 30 | auto r_map = boost::get(boost::edge_reverse, G); 31 | auto w_map = boost::get(boost::edge_weight, G); // new! 32 | const edge_desc e = boost::add_edge(from, to, G).first; 33 | const edge_desc rev_e = boost::add_edge(to, from, G).first; 34 | c_map[e] = capacity; 35 | c_map[rev_e] = 0; // reverse edge has no capacity! 36 | r_map[e] = rev_e; 37 | r_map[rev_e] = e; 38 | w_map[e] = cost; // new assign cost 39 | w_map[rev_e] = -cost; // new negative cost 40 | } 41 | }; 42 | 43 | void testcase() { 44 | int n, m, l; std::cin >> n >> m >> l; 45 | int src = n, dst = src + 1; 46 | graph g(dst + 1); 47 | edge_adder adder(g); 48 | auto c_map = boost::get(boost::edge_capacity, g); 49 | auto rc_map = boost::get(boost::edge_residual_capacity, g); 50 | 51 | adder.add_edge(src, 0, l, 0); 52 | adder.add_edge(n - 1, dst, l, 0); 53 | 54 | for (int i = 0; i < n - 1; i++) 55 | adder.add_edge(i, i + 1, l, 128); 56 | 57 | for (int i = 0; i < m; i++) { 58 | int x, y, q; std::cin >> x >> y >> q; 59 | adder.add_edge(x, y, 1, 128 * (y - x) - q); 60 | } 61 | 62 | boost::successive_shortest_path_nonnegative_weights(g, src, dst); 63 | int flow = 0; 64 | 65 | out_edge_it e, eend; 66 | for(boost::tie(e, eend) = boost::out_edges(boost::vertex(src, g), g); e != eend; ++e) 67 | flow += c_map[*e] - rc_map[*e]; 68 | 69 | std::cout << (n - 1) * flow * 128 - boost::find_flow_cost(g) << std::endl; 70 | } 71 | 72 | int main() { 73 | std::ios_base::sync_with_stdio(false); 74 | 75 | int t; 76 | std::cin >> t; 77 | for (int i = 0; i < t; ++i) 78 | testcase(); 79 | } 80 | -------------------------------------------------------------------------------- /Week06/CoinTossingTournament/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | // Graph Type with nested interior edge properties for flow algorithms 13 | typedef boost::adjacency_list_traits traits; 14 | typedef boost::adjacency_list>>> graph; 18 | 19 | typedef traits::vertex_descriptor vertex_desc; 20 | typedef traits::edge_descriptor edge_desc; 21 | 22 | // Custom edge adder class, highly recommended 23 | class edge_adder { 24 | graph &G; 25 | 26 | public: 27 | explicit edge_adder(graph &G) : G(G) {} 28 | 29 | void add_edge(int from, int to, long capacity) { 30 | auto c_map = boost::get(boost::edge_capacity, G); 31 | auto r_map = boost::get(boost::edge_reverse, G); 32 | const auto e = boost::add_edge(from, to, G).first; 33 | const auto rev_e = boost::add_edge(to, from, G).first; 34 | c_map[e] = capacity; 35 | c_map[rev_e] = 0; // reverse edge has no capacity! 36 | r_map[e] = rev_e; 37 | r_map[rev_e] = e; 38 | } 39 | }; 40 | 41 | void testcase() { 42 | int n, m; std::cin >> n >> m; 43 | std::vector sb(n, 0); 44 | std::vector> games; 45 | 46 | for (int i = 0; i < m; i++) { 47 | int a, b, c; std::cin >> a >> b >> c; 48 | 49 | if (c == 0) 50 | games.push_back(std::make_pair(a, b)); 51 | else if (c == 1) 52 | sb[a]++; 53 | else 54 | sb[b]++; 55 | } 56 | 57 | int sum = 0; 58 | bool impossible = false; 59 | for (int i = 0; i < n; i++) { 60 | int s; std::cin >> s; 61 | sb[i] = s - sb[i]; 62 | sum += sb[i]; 63 | 64 | if (sb[i] < 0) 65 | impossible = true; 66 | } 67 | 68 | if (impossible || (int)games.size() != sum) { 69 | std::cout << "no" << std::endl; 70 | return; 71 | } 72 | 73 | int k = (int)games.size(), src = k + n, dst = k + n + 1; 74 | graph g(k + n + 2); 75 | edge_adder adder(g); 76 | 77 | for (int i = 0; i < k; i++) { 78 | adder.add_edge(src, i, 1); 79 | adder.add_edge(i, k + games[i].first, 1); 80 | adder.add_edge(i, k + games[i].second, 1); 81 | } 82 | 83 | for (int i = 0; i < n; i++) 84 | if (sb[i] != 0) 85 | adder.add_edge(k + i, dst, sb[i]); 86 | 87 | long flow = boost::push_relabel_max_flow(g, src, dst); 88 | std::cout << ((flow == k) ? "yes" : "no") << std::endl; 89 | } 90 | 91 | int main() { 92 | std::ios_base::sync_with_stdio(false); 93 | 94 | int t; 95 | std::cin >> t; 96 | for (int i = 0; i < t; ++i) 97 | testcase(); 98 | } 99 | -------------------------------------------------------------------------------- /PreviousYears/2022/LightTheStage/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | typedef CGAL::Exact_predicates_inexact_constructions_kernel K; 16 | typedef std::size_t Index; 17 | typedef CGAL::Triangulation_vertex_base_with_info_2 Vb; 18 | typedef CGAL::Triangulation_face_base_2 Fb; 19 | typedef CGAL::Triangulation_data_structure_2 Tds; 20 | typedef CGAL::Delaunay_triangulation_2 Delaunay; 21 | 22 | typedef K::Point_2 P; 23 | typedef std::tuple Edge; 24 | typedef std::vector EdgeV; 25 | typedef std::pair IPoint; 26 | 27 | void testcase() { 28 | long m, n; std::cin >> m >> n; 29 | 30 | std::vector> players(m); 31 | for (int i = 0; i < m; ++i) { 32 | K::FT x, y, r; std::cin >> x >> y >> r; 33 | players[i] = {P(x, y), r}; 34 | } 35 | 36 | long h; std::cin >> h; 37 | std::vector points(n); 38 | for (Index i = 0; i < n; ++i) { 39 | K::FT x, y; std::cin >> x >> y; 40 | points[i] = {P(x, y), i}; 41 | } 42 | 43 | Delaunay t; 44 | t.insert(points.begin(), points.end()); 45 | std::vector winners; 46 | 47 | for (long i = 0; i < m; i++) { 48 | K::FT min_dist = CGAL::squared_distance(P(0,0), P(0, h + players[i].second)); 49 | P closest = t.nearest_vertex(players[i].first)->point(); 50 | if (CGAL::squared_distance(players[i].first, closest) >= min_dist) 51 | winners.push_back(i); 52 | } 53 | 54 | if (winners.size() > 0) { 55 | for (const int i: winners) 56 | std::cout << i << " "; 57 | std::cout << std::endl; 58 | return; 59 | } 60 | 61 | int start = 1, end = n + 1; 62 | while (start < end) { 63 | int mid = (start + end) / 2; 64 | 65 | Delaunay t; 66 | t.insert(points.begin(), points.begin() + mid); 67 | 68 | std::vector w; 69 | for (long i = 0; i < m; i++) { 70 | K::FT min_dist = CGAL::squared_distance(P(0,0), P(0, h + players[i].second)); 71 | P closest = t.nearest_vertex(players[i].first)->point(); 72 | if (CGAL::squared_distance(players[i].first, closest) >= min_dist) 73 | w.push_back(i); 74 | } 75 | 76 | if (w.size() > 0) { 77 | start = mid + 1; 78 | winners = w; 79 | } else 80 | end = mid; 81 | } 82 | 83 | for (const int i: winners) 84 | std::cout << i << " "; 85 | std::cout << std::endl; 86 | } 87 | 88 | int main() { 89 | std::ios_base::sync_with_stdio(false); 90 | 91 | int t; 92 | std::cin >> t; 93 | for (int i = 0; i < t; ++i) 94 | testcase(); 95 | } 96 | -------------------------------------------------------------------------------- /Week11/DeanThomas/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | typedef CGAL::Exact_predicates_exact_constructions_kernel K; 17 | typedef K::Point_2 P; 18 | typedef std::size_t Index; 19 | typedef std::pair Info; 20 | typedef CGAL::Triangulation_vertex_base_2 Vb; 21 | typedef CGAL::Triangulation_face_base_with_info_2 Fb; 22 | typedef CGAL::Triangulation_data_structure_2 Tds; 23 | typedef CGAL::Delaunay_triangulation_2 Delaunay; 24 | 25 | void testcase() { 26 | long n, m, d; std::cin >> n >> m >> d; 27 | std::vector

points(n); 28 | std::priority_queue> q; 29 | 30 | for (int i = 0; i < n; ++i) { 31 | long x, y; std::cin >> x >> y; 32 | points[i] = P(x, y); 33 | } 34 | 35 | Delaunay t; 36 | t.insert(points.begin(), points.end()); 37 | 38 | for (auto f = t.finite_faces_begin(); f != t.finite_faces_end(); ++f){ 39 | f->info() = {false, CGAL::squared_distance(t.dual(f), f->vertex(0)->point())}; 40 | 41 | for (int i = 0; i < 3; i++) 42 | if (t.is_infinite(f->neighbor(i))) 43 | f->info().second = CGAL::max(f->info().second, t.segment(f, i).squared_length()); 44 | 45 | q.push({f->info().second, f}); 46 | } 47 | 48 | while (!q.empty()) { 49 | auto curr = q.top(); q.pop(); 50 | auto f1 = curr.second; 51 | 52 | if (!f1->info().first) { 53 | for (int i = 0; i < 3; i++) { 54 | auto f2 = f1->neighbor(i); 55 | 56 | if (!t.is_infinite(f2) && !f2->info().first) { 57 | auto d = CGAL::min(f1->info().second, t.segment(f1, i).squared_length()); 58 | 59 | if (d > f2->info().second) { 60 | f2->info().second = d; 61 | q.push({f2->info().second, f2}); 62 | } 63 | } 64 | } 65 | 66 | f1->info().first = true; 67 | } 68 | } 69 | 70 | for (int i = 0; i < m; i++) { 71 | long x, y, s; std::cin >> x >> y >> s; 72 | K::FT r = CGAL::squared_distance(P(0, 0), P(0, d + s)); 73 | P p(x, y); 74 | 75 | if (r > CGAL::squared_distance(p, t.nearest_vertex(p)->point())) { 76 | std::cout << "n"; 77 | continue; 78 | } 79 | 80 | auto f = t.locate(p); 81 | if (t.is_infinite(f) || 4*r <= f->info().second) 82 | std::cout << "y"; 83 | else 84 | std::cout << "n"; 85 | } 86 | std::cout << std::endl; 87 | } 88 | 89 | int main() { 90 | std::ios_base::sync_with_stdio(false); 91 | 92 | int t; 93 | std::cin >> t; 94 | for (int i = 0; i < t; ++i) 95 | testcase(); 96 | } 97 | -------------------------------------------------------------------------------- /PreviousYears/2022/RevengeOfTheSith/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | typedef CGAL::Exact_predicates_inexact_constructions_kernel K; 17 | typedef std::size_t Index; 18 | typedef CGAL::Triangulation_vertex_base_with_info_2 Vb; 19 | typedef CGAL::Triangulation_face_base_2 Fb; 20 | typedef CGAL::Triangulation_data_structure_2 Tds; 21 | typedef CGAL::Delaunay_triangulation_2 Delaunay; 22 | 23 | typedef K::Point_2 P; 24 | typedef std::tuple Edge; 25 | typedef std::vector EdgeV; 26 | typedef std::pair IPoint; 27 | 28 | long n, r; 29 | 30 | int rebels(std::vector& points, const int k) { 31 | Delaunay t; 32 | t.insert(points.begin() + k, points.end()); 33 | 34 | EdgeV edges; 35 | edges.reserve(3*n); 36 | for (auto e = t.finite_edges_begin(); e != t.finite_edges_end(); ++e) { 37 | Index i1 = e->first->vertex((e->second+1)%3)->info(); 38 | Index i2 = e->first->vertex((e->second+2)%3)->info(); 39 | 40 | if (i1 > i2) std::swap(i1, i2); 41 | if (t.segment(e).squared_length() <= r * r) 42 | edges.emplace_back(i1, i2, t.segment(e).squared_length()); 43 | } 44 | 45 | std::sort(edges.begin(), edges.end(), 46 | [](const Edge& e1, const Edge& e2) -> bool { 47 | return std::get<2>(e1) < std::get<2>(e2); 48 | }); 49 | 50 | boost::disjoint_sets_with_storage<> uf(n); 51 | Index n_components = n; 52 | for (EdgeV::const_iterator e = edges.begin(); e != edges.end(); ++e) { 53 | Index c1 = uf.find_set(std::get<0>(*e)); 54 | Index c2 = uf.find_set(std::get<1>(*e)); 55 | if (c1 != c2) { 56 | uf.link(c1, c2); 57 | if (--n_components == 1) break; 58 | } 59 | } 60 | 61 | std::vector occs(n, 0); 62 | for (int i = k; i < n; i++) 63 | occs[uf.find_set(i)]++; 64 | 65 | return std::min(k, *std::max_element(occs.begin(), occs.end())); 66 | } 67 | 68 | void testcase() { 69 | std::cin >> n >> r; 70 | 71 | std::vector points(n); 72 | for (Index i = 0; i < n; ++i) { 73 | int x, y; std::cin >> x >> y; 74 | points[i] = {P(x, y), i}; 75 | } 76 | 77 | int start = 1, end = (n / 2) + 1; 78 | while (start < end) { 79 | int mid = start + (end - start) / 2; 80 | int r1 = rebels(points, mid), r2 = rebels(points, mid + 1); 81 | 82 | if (r1 < r2) 83 | start = mid + 1; 84 | else 85 | end = mid; 86 | } 87 | 88 | std::cout << start << std::endl; 89 | } 90 | 91 | int main() { 92 | std::ios_base::sync_with_stdio(false); 93 | 94 | int t; 95 | std::cin >> t; 96 | for (int i = 0; i < t; ++i) 97 | testcase(); 98 | } 99 | -------------------------------------------------------------------------------- /Week13/Schneewittchen/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | typedef int IT; 14 | typedef CGAL::Gmpz ET; 15 | typedef CGAL::Quadratic_program Program; 16 | typedef CGAL::Quadratic_program_solution Solution; 17 | 18 | int n, m; 19 | std::vector> adj, contents; 20 | std::vector dangerous, danger_ids; 21 | 22 | void dfs(const int root, const int curr, Program& lp) { 23 | int idx = danger_ids[curr], root_idx = danger_ids[root]; 24 | 25 | if (curr != root && idx >= 0) 26 | for (int j = 0; j < m; j++) 27 | lp.set_a(idx*m + j, root_idx*(m + 1) + j, -1); 28 | else { 29 | if (curr != root) 30 | for (int j = 0; j < m; j++) 31 | contents[root][j] += contents[curr][j]; 32 | 33 | for (const int child: adj[curr]) 34 | dfs(root, child, lp); 35 | } 36 | 37 | if (curr == root) { 38 | for (int j = 0; j < m; j++) { 39 | lp.set_a(root_idx*m + j, root_idx*(m + 1) + j, 2); 40 | lp.set_b(root_idx*(m + 1) + j, 2 * contents[root][j]); 41 | } 42 | } 43 | } 44 | 45 | void testcase() { 46 | std::cin >> n >> m; 47 | Program lp (CGAL::SMALLER, true, 0, false, 0); 48 | int idx = 1; 49 | 50 | adj = std::vector>(n); 51 | contents = std::vector>(n, std::vector(m)); 52 | dangerous = std::vector(); 53 | danger_ids = std::vector(n, -1); 54 | 55 | for (int i = 0; i < n; i++) { 56 | int d; std::cin >> d; 57 | 58 | if (d >= 0) { 59 | danger_ids[i] = idx; 60 | dangerous.push_back(i); 61 | 62 | for (int j = 0; j < m; j++) 63 | lp.set_a(idx*m + j, idx*(m + 1) + m, 1); 64 | 65 | lp.set_b(idx*(m + 1) + m, d); 66 | idx++; 67 | } 68 | 69 | for (int j = 0; j < m; j++) 70 | std::cin >> contents[i][j]; 71 | } 72 | 73 | for (int i = 0; i < n - 1; i++) { 74 | int u, v; std::cin >> u >> v; 75 | adj[v].push_back(u); 76 | } 77 | 78 | danger_ids[0] = 0; 79 | dangerous.push_back(0); 80 | for (const int root: dangerous) 81 | dfs(root, root, lp); 82 | 83 | for (int j = 0; j < m; j++) { 84 | int c, s, p; std::cin >> c >> s >> p; 85 | lp.set_a(j, idx*(m + 1) + j, -1); 86 | lp.set_a(idx*m + j, idx*(m + 1) + j, -1); 87 | lp.set_b(idx*(m + 1) + j, -c); 88 | 89 | lp.set_a(idx*m + j, idx*(m + 1) + m + j, 1); 90 | lp.set_b(idx*(m + 1) + m + j, s); 91 | 92 | lp.set_c(idx*m + j, p); 93 | } 94 | 95 | Solution s = CGAL::solve_linear_program(lp, ET()); 96 | if (s.is_infeasible()) 97 | std::cout << "Impossible!" << std::endl; 98 | else 99 | std::cout << (long)std::floor(CGAL::to_double(s.objective_value())) << std::endl; 100 | } 101 | 102 | int main() { 103 | std::ios_base::sync_with_stdio(false); 104 | 105 | int t; 106 | std::cin >> t; 107 | for (int i = 0; i < t; ++i) 108 | testcase(); 109 | } -------------------------------------------------------------------------------- /Week09/Canteen/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | typedef boost::adjacency_list_traits traits; 16 | typedef boost::adjacency_list > > > > graph; // new! weightmap corresponds to costs 21 | 22 | typedef boost::graph_traits::edge_descriptor edge_desc; 23 | typedef boost::graph_traits::out_edge_iterator out_edge_it; // Iterator 24 | 25 | class edge_adder { 26 | graph &G; 27 | 28 | public: 29 | explicit edge_adder(graph &G) : G(G) {} 30 | void add_edge(int from, int to, long capacity, long cost) { 31 | auto c_map = boost::get(boost::edge_capacity, G); 32 | auto r_map = boost::get(boost::edge_reverse, G); 33 | auto w_map = boost::get(boost::edge_weight, G); 34 | const edge_desc e = boost::add_edge(from, to, G).first; 35 | const edge_desc rev_e = boost::add_edge(to, from, G).first; 36 | c_map[e] = capacity; 37 | c_map[rev_e] = 0; 38 | r_map[e] = rev_e; 39 | r_map[rev_e] = e; 40 | w_map[e] = cost; 41 | w_map[rev_e] = -cost; 42 | } 43 | }; 44 | 45 | void testcase() { 46 | int n; std::cin >> n; 47 | int src = n, dst = src + 1; 48 | graph g(n + 2); 49 | edge_adder adder(g); 50 | auto c_map = boost::get(boost::edge_capacity, g); 51 | auto rc_map = boost::get(boost::edge_residual_capacity, g); 52 | 53 | for (int i = 0; i < n; i++) { 54 | int a, c; std::cin >> a >> c; 55 | adder.add_edge(src, i, a, c); 56 | } 57 | 58 | int total = 0; 59 | for (int i = 0; i < n; i++) { 60 | int s, p; std::cin >> s >> p; 61 | adder.add_edge(i, dst, s, 20 - p); 62 | total += s; 63 | } 64 | 65 | for (int i = 0; i < n - 1; i++) { 66 | int v, e; std::cin >> v >> e; 67 | adder.add_edge(i, i + 1, v, e); 68 | } 69 | 70 | boost::successive_shortest_path_nonnegative_weights(g, src, dst); 71 | int cost = boost::find_flow_cost(g); 72 | 73 | int fed_students = 0; 74 | out_edge_it e, eend; 75 | for(boost::tie(e, eend) = boost::out_edges(boost::vertex(dst, g), g); e != eend; ++e) 76 | fed_students += rc_map[*e] - c_map[*e]; 77 | 78 | int revenue = 20 * fed_students - cost; 79 | std::cout << ((fed_students == total) ? "possible " : "impossible ") << fed_students << " " << revenue<< std::endl; 80 | } 81 | 82 | int main() { 83 | std::ios_base::sync_with_stdio(false); 84 | 85 | int t; 86 | std::cin >> t; 87 | for (int i = 0; i < t; ++i) 88 | testcase(); 89 | } 90 | -------------------------------------------------------------------------------- /Week09/RealEstateMarket/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | typedef boost::adjacency_list_traits traits; 16 | typedef boost::adjacency_list > > > > graph; // new! weightmap corresponds to costs 21 | 22 | typedef boost::graph_traits::edge_descriptor edge_desc; 23 | typedef boost::graph_traits::out_edge_iterator out_edge_it; // Iterator 24 | 25 | class edge_adder { 26 | graph &G; 27 | 28 | public: 29 | explicit edge_adder(graph &G) : G(G) {} 30 | void add_edge(int from, int to, long capacity, long cost) { 31 | auto c_map = boost::get(boost::edge_capacity, G); 32 | auto r_map = boost::get(boost::edge_reverse, G); 33 | auto w_map = boost::get(boost::edge_weight, G); 34 | const edge_desc e = boost::add_edge(from, to, G).first; 35 | const edge_desc rev_e = boost::add_edge(to, from, G).first; 36 | c_map[e] = capacity; 37 | c_map[rev_e] = 0; 38 | r_map[e] = rev_e; 39 | r_map[rev_e] = e; 40 | w_map[e] = cost; 41 | w_map[rev_e] = -cost; 42 | } 43 | }; 44 | 45 | void testcase() { 46 | int n, m, s; std::cin >> n >> m >> s; 47 | int lands = n, states = lands + m, src = states + s, dst = src + 1; 48 | graph g(dst + 1); 49 | edge_adder adder(g); 50 | auto c_map = boost::get(boost::edge_capacity, g); 51 | auto rc_map = boost::get(boost::edge_residual_capacity, g); 52 | 53 | for (int i = 0; i < s; i++) { 54 | int l; std::cin >> l; 55 | adder.add_edge(states + i, dst, l, 0); 56 | } 57 | 58 | for (int i = 0; i < m; i++) { 59 | int j; std::cin >> j; 60 | adder.add_edge(lands + i, states + j - 1, 1, 0); 61 | } 62 | 63 | for (int i = 0; i < n; i++) { 64 | adder.add_edge(src, i, 1, 0); 65 | for (int j = 0; j < m; j++) { 66 | int b; std::cin >> b; 67 | adder.add_edge(i, lands + j, 1, 100 - b); 68 | } 69 | } 70 | 71 | boost::successive_shortest_path_nonnegative_weights(g, src, dst); 72 | int cost = boost::find_flow_cost(g); 73 | 74 | int sold = 0; 75 | out_edge_it e, eend; 76 | for(boost::tie(e, eend) = boost::out_edges(boost::vertex(dst, g), g); e != eend; ++e) 77 | sold += rc_map[*e] - c_map[*e]; 78 | 79 | int revenue = 100 * sold - cost; 80 | std::cout << sold << " " << revenue << std::endl; 81 | } 82 | 83 | int main() { 84 | std::ios_base::sync_with_stdio(false); 85 | 86 | int t; 87 | std::cin >> t; 88 | for (int i = 0; i < t; ++i) 89 | testcase(); 90 | } 91 | -------------------------------------------------------------------------------- /Week12/WorldCup/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | typedef CGAL::Exact_predicates_inexact_constructions_kernel K; 17 | typedef CGAL::Delaunay_triangulation_2 Delaunay; 18 | typedef K::Point_2 P; 19 | typedef K::Segment_2 S; 20 | typedef K::Circle_2 C; 21 | 22 | typedef int IT; 23 | typedef CGAL::Gmpz ET; 24 | 25 | typedef CGAL::Quadratic_program Program; 26 | typedef CGAL::Quadratic_program_solution Solution; 27 | 28 | void testcase() { 29 | int n, m, c; std::cin >> n >> m >> c; 30 | Program lp (CGAL::SMALLER, true, 0, false, 0); 31 | 32 | std::vector alcohol(n); 33 | std::vector

warehouses(n), stadiums(m); 34 | std::vector> revenues(n, std::vector(m)); 35 | 36 | for (int i = 0; i < n; i++) { 37 | int x, y, s, a; std::cin >> x >> y >> s >> a; 38 | warehouses[i] = P(x, y); 39 | 40 | lp.set_b(i, s); 41 | for (int j = 0; j < m; j++) 42 | lp.set_a(i*m + j, i, 1); 43 | 44 | alcohol[i] = a; 45 | } 46 | 47 | for (int j = 0; j < m; j++) { 48 | int x, y, d, u; std::cin >> x >> y >> d >> u; 49 | stadiums[j] = P(x, y); 50 | 51 | lp.set_b(n + j, d); 52 | lp.set_b(n + m + j, -d); 53 | lp.set_b(n + 2*m + j, u * 100); 54 | 55 | for (int i = 0; i < n; i++) { 56 | lp.set_a(i*m + j, n + j, 1); 57 | lp.set_a(i*m + j, n + m + j, -1); 58 | lp.set_a(i*m + j, n + 2*m + j, alcohol[i]); 59 | } 60 | } 61 | 62 | Delaunay t; 63 | t.insert(warehouses.begin(), warehouses.end()); 64 | t.insert(stadiums.begin(), stadiums.end()); 65 | 66 | for (int i = 0; i < n; i++) { 67 | for (int j = 0; j < m; j++) { 68 | int r; std::cin >> r; 69 | revenues[i][j] = 100 * r; 70 | } 71 | } 72 | 73 | for (int i = 0; i < c; i++) { 74 | long x, y, r; std::cin >> x >> y >> r; 75 | P center = P(x, y); 76 | C contour = C(center, r * r); 77 | 78 | if (!contour.has_on_bounded_side(t.nearest_vertex(center)->point())) 79 | continue; 80 | 81 | for (int i = 0; i < n; i++) { 82 | for (int j = 0; j < m; j++) { 83 | P w = warehouses[i], s = stadiums[j]; 84 | 85 | if (contour.has_on_bounded_side(w) != contour.has_on_bounded_side(s)) 86 | revenues[i][j] -= 1; 87 | } 88 | } 89 | } 90 | 91 | for (int i = 0; i < n; i++) 92 | for (int j = 0; j < m; j++) 93 | lp.set_c(i*m + j, -revenues[i][j]); 94 | 95 | Solution s = CGAL::solve_linear_program(lp, ET()); 96 | if (s.is_infeasible()) 97 | std::cout << "RIOT!" << std::endl; 98 | else 99 | std::cout << (long)std::floor(CGAL::to_double(-s.objective_value() / 100)) << std::endl; 100 | } 101 | 102 | int main() { 103 | std::ios_base::sync_with_stdio(false); 104 | 105 | int t; 106 | std::cin >> t; 107 | for (int i = 0; i < t; ++i) 108 | testcase(); 109 | } 110 | -------------------------------------------------------------------------------- /Week06/London/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | // Graph Type with nested interior edge properties for flow algorithms 13 | typedef boost::adjacency_list_traits traits; 14 | typedef boost::adjacency_list>>> graph; 18 | 19 | typedef traits::vertex_descriptor vertex_desc; 20 | typedef traits::edge_descriptor edge_desc; 21 | 22 | // Custom edge adder class, highly recommended 23 | class edge_adder { 24 | graph &G; 25 | 26 | public: 27 | explicit edge_adder(graph &G) : G(G) {} 28 | 29 | void add_edge(int from, int to, long capacity) { 30 | auto c_map = boost::get(boost::edge_capacity, G); 31 | auto r_map = boost::get(boost::edge_reverse, G); 32 | const auto e = boost::add_edge(from, to, G).first; 33 | const auto rev_e = boost::add_edge(to, from, G).first; 34 | c_map[e] = capacity; 35 | c_map[rev_e] = 0; // reverse edge has no capacity! 36 | r_map[e] = rev_e; 37 | r_map[rev_e] = e; 38 | } 39 | }; 40 | 41 | const int ALPHABET = 26; 42 | 43 | void testcase() { 44 | int h, w; std::cin >> h >> w; 45 | std::vector> front(h, std::vector(w)), back(h, std::vector(w)); 46 | int in_pairs[ALPHABET][ALPHABET] = {0}; 47 | int out_occs[ALPHABET] = {0}; 48 | 49 | std::string line; std::cin >> line; 50 | for (auto c: line) 51 | out_occs[c - 'A']++; 52 | 53 | for (int i = 0; i < h; i++) 54 | for (int j = 0; j < w; j++) { 55 | char x; std::cin >> x; 56 | front[i][j] = x - 'A'; 57 | } 58 | 59 | for (int i = 0; i < h; i++) 60 | for (int j = w - 1; j >= 0; j--) { 61 | char x; std::cin >> x; 62 | back[i][j] = x - 'A'; 63 | } 64 | 65 | for (int i = 0; i < h; i++) 66 | for (int j = 0; j < w; j++) { 67 | int f = front[i][j], b = back[i][j]; 68 | in_pairs[std::min(f, b)][std::max(f, b)]++; 69 | } 70 | 71 | graph g((ALPHABET + 1) * ALPHABET + 2); 72 | edge_adder adder(g); 73 | const int src = (ALPHABET + 1) * ALPHABET, dst = src + 1; 74 | for (int f = 0; f < ALPHABET; f++) 75 | for (int b = f; b < ALPHABET; b++) { 76 | adder.add_edge(src, f * ALPHABET + b, in_pairs[f][b]); 77 | adder.add_edge(f * ALPHABET + b, ALPHABET * ALPHABET + f, in_pairs[f][b]); 78 | adder.add_edge(f * ALPHABET + b, ALPHABET * ALPHABET + b, in_pairs[f][b]); 79 | } 80 | 81 | for (int i = 0; i < ALPHABET; i++) 82 | adder.add_edge(ALPHABET * ALPHABET + i, dst, out_occs[i]); 83 | 84 | long flow = boost::push_relabel_max_flow(g, src, dst); 85 | std::cout << ((flow == (long)line.length()) ? "Yes" : "No") << std::endl; 86 | } 87 | 88 | int main() { 89 | std::ios_base::sync_with_stdio(false); 90 | 91 | int t; 92 | std::cin >> t; 93 | for (int i = 0; i < t; ++i) 94 | testcase(); 95 | } 96 | -------------------------------------------------------------------------------- /PreviousYears/2022/Marathon/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | typedef boost::adjacency_list > graph; 15 | typedef boost::property_map::type weight_map; 16 | 17 | #include 18 | #include 19 | 20 | typedef boost::adjacency_list_traits traits; 21 | typedef boost::adjacency_list>>> flow_graph; 25 | typedef boost::graph_traits::edge_descriptor edge_desc; 26 | typedef boost::graph_traits::out_edge_iterator out_edge_it; 27 | 28 | class edge_adder { 29 | flow_graph &G; 30 | 31 | public: 32 | explicit edge_adder(flow_graph &G) : G(G) {} 33 | 34 | void add_edge(int from, int to, long capacity) { 35 | auto c_map = boost::get(boost::edge_capacity, G); 36 | auto r_map = boost::get(boost::edge_reverse, G); 37 | const edge_desc e = boost::add_edge(from, to, G).first; 38 | const edge_desc rev_e = boost::add_edge(to, from, G).first; 39 | c_map[e] = capacity; 40 | c_map[rev_e] = 0; 41 | r_map[e] = rev_e; 42 | r_map[rev_e] = e; 43 | } 44 | }; 45 | 46 | void testcase() { 47 | int n, m, s, f; std::cin >> n >> m >> s >> f; 48 | std::vector>> adj(n, std::vector>()); 49 | graph g(n); 50 | 51 | flow_graph fg(n); 52 | edge_adder adder(fg); 53 | 54 | for (int i = 0; i < m; i++) { 55 | int a, b, c, d; std::cin >> a >> b >> c >> d; 56 | boost::add_edge(a, b, d, g); 57 | adj[a].push_back({b, c, d}); 58 | adj[b].push_back({a, c, d}); 59 | } 60 | 61 | std::vector dist_map(n); 62 | boost::dijkstra_shortest_paths(g, s, 63 | boost::distance_map(boost::make_iterator_property_map( 64 | dist_map.begin(), boost::get(boost::vertex_index, g)))); 65 | 66 | std::queue q; 67 | std::vector visited(n, false); 68 | q.push(f); 69 | while (!q.empty()) { 70 | int curr = q.front(); q.pop(); 71 | if (curr == s || visited[curr]) 72 | continue; 73 | 74 | visited[curr] = true; 75 | int min_dist = dist_map[curr]; 76 | for (const auto &[pred, c, d]: adj[curr]) { 77 | if (dist_map[pred] != std::numeric_limits::max() 78 | && dist_map[pred] + d == min_dist 79 | ) { 80 | q.push(pred); 81 | adder.add_edge(pred, curr, c); 82 | } 83 | } 84 | } 85 | 86 | std::cout << boost::push_relabel_max_flow(fg, s, f) << std::endl; 87 | } 88 | 89 | int main() { 90 | std::ios_base::sync_with_stdio(false); 91 | 92 | int t; 93 | std::cin >> t; 94 | for (int i = 0; i < t; ++i) 95 | testcase(); 96 | } 97 | -------------------------------------------------------------------------------- /Week10/Clues/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | typedef boost::adjacency_list graph; 21 | 22 | typedef CGAL::Exact_predicates_inexact_constructions_kernel K; 23 | typedef K::Point_2 P; 24 | typedef CGAL::Triangulation_vertex_base_with_info_2 Vb; 25 | typedef CGAL::Triangulation_face_base_2 Fb; 26 | typedef CGAL::Triangulation_data_structure_2 Tds; 27 | typedef CGAL::Delaunay_triangulation_2 Delaunay; 28 | 29 | typedef std::pair IPoint; 30 | typedef Tds::Vertex_handle VH; 31 | 32 | void testcase() { 33 | long n, m, r; std::cin >> n >> m >> r; 34 | 35 | std::vector points; 36 | points.reserve(n); 37 | for (int i = 0; i < n; ++i) { 38 | int x, y; std::cin >> x >> y; 39 | points.emplace_back(P(x, y), i); 40 | } 41 | 42 | Delaunay t; 43 | t.insert(points.begin(), points.end()); 44 | 45 | graph g(n); 46 | for (auto v = t.finite_vertices_begin(); v != t.finite_vertices_end(); ++v) { 47 | std::set visited; 48 | std::queue q; 49 | 50 | q.push(v); 51 | visited.insert(v); 52 | 53 | while (!q.empty()) { 54 | auto v1 = q.front(); q.pop(); 55 | 56 | if (v1->info() != v->info()) 57 | boost::add_edge(v->info(), v1->info(), g); 58 | 59 | auto v2 = v1->incident_vertices(); 60 | do { 61 | if (!t.is_infinite(v2) 62 | && visited.find(v2) == visited.end() 63 | && CGAL::squared_distance(v->point(), v2->point()) <= r * r 64 | ){ 65 | visited.insert(v2); 66 | q.push(v2); 67 | } 68 | } while (++v2 != v1->incident_vertices()); 69 | } 70 | } 71 | 72 | bool interferences = !boost::is_bipartite(g); 73 | 74 | std::vector components(n); 75 | boost::connected_components(g, boost::make_iterator_property_map(components.begin(), boost::get(boost::vertex_index, g))); 76 | 77 | for (int i = 0; i < m; i++) { 78 | int x1, y1, x2, y2; std::cin >> x1 >> y1 >> x2 >> y2; 79 | P a(x1, y1), b(x2, y2); 80 | 81 | auto va = t.nearest_vertex(a), vb = t.nearest_vertex(b); 82 | long dist_a = (long)CGAL::squared_distance(a, va->point()); 83 | long dist_b = (long)CGAL::squared_distance(b, vb->point()); 84 | 85 | if (interferences) 86 | std::cout << "n"; 87 | else if ((long)CGAL::squared_distance(a, b) <= r * r) 88 | std::cout << "y"; 89 | else if (dist_a <= r * r && dist_b <= r * r && components[va->info()] == components[vb->info()]) 90 | std::cout << "y"; 91 | else 92 | std::cout << "n"; 93 | } 94 | 95 | std::cout << std::endl; 96 | } 97 | 98 | int main() { 99 | std::ios_base::sync_with_stdio(false); 100 | 101 | int t; 102 | std::cin >> t; 103 | for (int i = 0; i < t; ++i) 104 | testcase(); 105 | } 106 | -------------------------------------------------------------------------------- /Week09/Idefix/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | using K = CGAL::Exact_predicates_inexact_constructions_kernel; 16 | using P = K::Point_2; 17 | 18 | using Index = std::size_t; 19 | using Vb = CGAL::Triangulation_vertex_base_with_info_2; 20 | using Fb = CGAL::Triangulation_face_base_2; 21 | using Tds = CGAL::Triangulation_data_structure_2; 22 | using Delaunay = CGAL::Delaunay_triangulation_2; 23 | 24 | using Edge = std::tuple; 25 | using EdgeV = std::vector; 26 | using IPoint = std::pair; 27 | using Bones = std::vector>; 28 | 29 | int max_bones(EdgeV& edges, Bones& bones, long n, long s) { 30 | boost::disjoint_sets_with_storage<> uf(n); 31 | Index n_components = n; 32 | 33 | for (EdgeV::const_iterator e = edges.begin(); e != edges.end() && n_components > 1; ++e) { 34 | if (std::get<2>(*e) > s) 35 | break; 36 | 37 | Index c1 = uf.find_set(std::get<0>(*e)); 38 | Index c2 = uf.find_set(std::get<1>(*e)); 39 | if (c1 != c2) { 40 | uf.link(c1, c2); 41 | --n_components; 42 | } 43 | } 44 | 45 | std::vector covered_bones(n, 0); 46 | for (const auto [i, dist]: bones) 47 | if (4 * dist <= s) 48 | covered_bones[uf.find_set(i)]++; 49 | 50 | return *std::max_element(covered_bones.begin(), covered_bones.end()); 51 | } 52 | 53 | void testcase() { 54 | long n, m, s, k; std::cin >> n >> m >> s >> k; 55 | std::vector trees(n); 56 | 57 | for (int i = 0; i < n; i++) { 58 | int x, y; std::cin >> x >> y; 59 | trees[i] = std::make_pair(P(x, y), i); 60 | } 61 | 62 | Delaunay tr; 63 | tr.insert(trees.begin(), trees.end()); 64 | 65 | Bones bones(m); 66 | for (int i = 0; i < m; i++) { 67 | int x, y; std::cin >> x >> y; 68 | P p(x, y); 69 | auto nearest = tr.nearest_vertex(p); 70 | long dist = CGAL::squared_distance(p, nearest->point()); 71 | 72 | bones[i] = std::make_pair(nearest->info(), dist); 73 | } 74 | 75 | EdgeV edges; 76 | edges.reserve(3*n); 77 | for (auto e = tr.finite_edges_begin(); e != tr.finite_edges_end(); ++e) { 78 | Index i1 = e->first->vertex((e->second+1)%3)->info(); 79 | Index i2 = e->first->vertex((e->second+2)%3)->info(); 80 | 81 | if (i1 > i2) std::swap(i1, i2); 82 | edges.emplace_back(i1, i2, tr.segment(e).squared_length()); 83 | } 84 | std::sort(edges.begin(), edges.end(), 85 | [](const Edge& e1, const Edge& e2) -> bool { 86 | return std::get<2>(e1) < std::get<2>(e2); 87 | }); 88 | 89 | long start = 0, end = 1L << 51; 90 | while (start < end) { 91 | long mid = start + (end - start) / 2; 92 | 93 | if (max_bones(edges, bones, n, mid) >= k) 94 | end = mid; 95 | else 96 | start = mid + 1; 97 | } 98 | 99 | std::cout << max_bones(edges, bones, n, s) << " " << end << std::endl; 100 | } 101 | 102 | int main() { 103 | std::ios_base::sync_with_stdio(false); 104 | 105 | int t; 106 | std::cin >> t; 107 | for (int i = 0; i < t; ++i) 108 | testcase(); 109 | } 110 | -------------------------------------------------------------------------------- /Week09/PlacingKnights/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | typedef boost::adjacency_list_traits traits; 15 | typedef boost::adjacency_list > > > graph; 19 | typedef boost::graph_traits::edge_descriptor edge_desc; 20 | typedef boost::graph_traits::out_edge_iterator out_edge_it; 21 | 22 | class edge_adder { 23 | graph &G; 24 | 25 | public: 26 | explicit edge_adder(graph &G) : G(G) {} 27 | 28 | void add_edge(int from, int to, long capacity) { 29 | auto c_map = boost::get(boost::edge_capacity, G); 30 | auto r_map = boost::get(boost::edge_reverse, G); 31 | const edge_desc e = boost::add_edge(from, to, G).first; 32 | const edge_desc rev_e = boost::add_edge(to, from, G).first; 33 | c_map[e] = capacity; 34 | c_map[rev_e] = 0; 35 | r_map[e] = rev_e; 36 | r_map[rev_e] = e; 37 | } 38 | }; 39 | 40 | void testcase() { 41 | int n; std::cin >> n; 42 | int src = n * n, dst = src + 1; 43 | graph g(dst + 1); 44 | edge_adder adder(g); 45 | auto rc_map = boost::get(boost::edge_residual_capacity, g); 46 | 47 | int board[n][n]; 48 | for (int i = 0; i < n; i++) 49 | for (int j = 0; j < n; j++) 50 | std::cin >> board[i][j]; 51 | 52 | for (int i = 0; i < n; i++) 53 | for (int j = 0; j < n; j++) 54 | if (board[i][j]) { 55 | if ((i + j) % 2 != 0) 56 | adder.add_edge(i * n + j, dst, 1); 57 | else { 58 | int x_offsets[8] = {2, 2, 1, 1, -1, -1, -2, -2}; 59 | int y_offsets[8] = {1, -1, 2, -2, 2, -2, 1, -1}; 60 | 61 | for (int offset = 0; offset < 8; offset++) { 62 | int x = j + x_offsets[offset], y = i + y_offsets[offset]; 63 | 64 | if (x >= 0 && x < n && y >= 0 && y < n && board[y][x]) 65 | adder.add_edge(i * n + j, y * n + x, 1); 66 | } 67 | 68 | adder.add_edge(src, i * n + j, 1); 69 | } 70 | } 71 | 72 | boost::push_relabel_max_flow(g, src, dst); 73 | std::vector vis(n * n + 2, false); 74 | std::queue Q; 75 | vis[src] = true; 76 | Q.push(src); 77 | while (!Q.empty()) { 78 | const int u = Q.front(); 79 | Q.pop(); 80 | 81 | out_edge_it ebeg, eend; 82 | for (boost::tie(ebeg, eend) = boost::out_edges(u, g); ebeg != eend; ++ebeg) { 83 | const int v = boost::target(*ebeg, g); 84 | if (rc_map[*ebeg] == 0 || vis[v]) continue; 85 | vis[v] = true; 86 | Q.push(v); 87 | } 88 | } 89 | 90 | int count = 0; 91 | for (int i = 0; i < n; i++) 92 | for (int j = 0; j < n; j++) { 93 | if (board[i][j]) { 94 | if ((i + j) % 2 != 0) 95 | count += 1 - vis[i * n + j]; 96 | else 97 | count += vis[i * n + j]; 98 | } 99 | } 100 | 101 | std::cout << count << std::endl; 102 | } 103 | 104 | int main() { 105 | std::ios_base::sync_with_stdio(false); 106 | 107 | int t; 108 | std::cin >> t; 109 | for (int i = 0; i < t; ++i) 110 | testcase(); 111 | } 112 | -------------------------------------------------------------------------------- /Exam/P2/MadTeaParty/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | typedef boost::adjacency_list_traits traits; 15 | typedef boost::adjacency_list > > > graph; 19 | typedef boost::graph_traits::edge_descriptor edge_desc; 20 | typedef boost::graph_traits::out_edge_iterator out_edge_it; 21 | 22 | class edge_adder { 23 | graph &G; 24 | 25 | public: 26 | explicit edge_adder(graph &G) : G(G) {} 27 | 28 | void add_edge(int from, int to, long capacity) { 29 | auto c_map = boost::get(boost::edge_capacity, G); 30 | auto r_map = boost::get(boost::edge_reverse, G); 31 | const edge_desc e = boost::add_edge(from, to, G).first; 32 | const edge_desc rev_e = boost::add_edge(to, from, G).first; 33 | c_map[e] = capacity; 34 | c_map[rev_e] = 0; 35 | r_map[e] = rev_e; 36 | r_map[rev_e] = e; 37 | } 38 | }; 39 | 40 | const int di[6] = {-1, -1, 0, 0, 1, 1}; 41 | const int dj[6] = {-1, 1, -1, 1, -1, 1}; 42 | 43 | void testcase() { 44 | int n, m; std::cin >> n >> m; 45 | std::vector> occs(n, std::vector(m)); 46 | 47 | int src = n * m, dst = src + 1; 48 | graph g(dst + 1); 49 | edge_adder adder(g); 50 | auto rc_map = boost::get(boost::edge_residual_capacity, g); 51 | 52 | for (int i = 0; i < n; i++) 53 | for (int j = 0; j < m; j++) 54 | std::cin >> occs[i][j]; 55 | 56 | for (int i = 0; i < n; i++) { 57 | for (int j = 0; j < m; j++) { 58 | if (occs[i][j]) { 59 | if (j % 2 == 0) { 60 | adder.add_edge(i*m + j, dst, 1); 61 | continue; 62 | } 63 | 64 | adder.add_edge(src, i*m + j, 1); 65 | for (int k = 0; k < 6; k++) { 66 | int tgt_i = i + di[k], tgt_j = j + dj[k]; 67 | 68 | if (tgt_i >= 0 && tgt_i < n && tgt_j >= 0 && tgt_j < m && occs[tgt_i][tgt_j]) 69 | adder.add_edge(i*m + j, tgt_i*m + tgt_j, 1); 70 | } 71 | } 72 | } 73 | } 74 | 75 | boost::push_relabel_max_flow(g, src, dst); 76 | 77 | std::vector vis(dst + 1, false); 78 | std::queue Q; 79 | 80 | vis[src] = true; 81 | Q.push(src); 82 | while (!Q.empty()) { 83 | const int u = Q.front(); Q.pop(); 84 | 85 | out_edge_it ebeg, eend; 86 | for (boost::tie(ebeg, eend) = boost::out_edges(u, g); ebeg != eend; ++ebeg) { 87 | const int v = boost::target(*ebeg, g); 88 | if (rc_map[*ebeg] == 0 || vis[v]) continue; 89 | vis[v] = true; 90 | Q.push(v); 91 | } 92 | } 93 | 94 | int count = 0; 95 | for (int i = 0; i < n; i++) { 96 | for (int j = 0; j < m; j++) { 97 | if (occs[i][j]) { 98 | if ((vis[i*m + j] && j % 2 != 0) || (!vis[i*m + j] && j % 2 == 0)) 99 | count++; 100 | } 101 | } 102 | } 103 | 104 | std::cout << count << std::endl; 105 | } 106 | 107 | int main() { 108 | std::ios_base::sync_with_stdio(false); 109 | 110 | int t; 111 | std::cin >> t; 112 | for (int i = 0; i < t; ++i) 113 | testcase(); 114 | } 115 | -------------------------------------------------------------------------------- /PreviousYears/2022/LudoBagman/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | typedef boost::adjacency_list_traits traits; 16 | typedef boost::adjacency_list > > > > graph; 21 | 22 | typedef boost::graph_traits::edge_descriptor edge_desc; 23 | typedef boost::graph_traits::out_edge_iterator out_edge_it; 24 | 25 | class edge_adder { 26 | graph &G; 27 | 28 | public: 29 | explicit edge_adder(graph &G) : G(G) {} 30 | void add_edge(int from, int to, long capacity, long cost) { 31 | auto c_map = boost::get(boost::edge_capacity, G); 32 | auto r_map = boost::get(boost::edge_reverse, G); 33 | auto w_map = boost::get(boost::edge_weight, G); 34 | const edge_desc e = boost::add_edge(from, to, G).first; 35 | const edge_desc rev_e = boost::add_edge(to, from, G).first; 36 | c_map[e] = capacity; 37 | c_map[rev_e] = 0; 38 | r_map[e] = rev_e; 39 | r_map[rev_e] = e; 40 | w_map[e] = cost; 41 | w_map[rev_e] = -cost; 42 | } 43 | }; 44 | 45 | void testcase() { 46 | int e, w, m, d, p, l; std::cin >> e >> w >> m >> d >> p >> l; 47 | int src = e + w, extra = src + 1, danger = extra + 1; 48 | int dst = danger + 1, extra_dst = dst + 1; 49 | graph g(extra_dst + 1); 50 | edge_adder adder(g); 51 | 52 | if (p < l * std::max(e, w)) { 53 | std::cout << "No schedule!" << std::endl; 54 | 55 | for (int i = 0; i < m + d; i++) { 56 | int u, v, r; std::cin >> u >> v >> r; 57 | } 58 | return; 59 | } 60 | 61 | adder.add_edge(src, extra, p - l*e, 0); 62 | adder.add_edge(extra, danger, p - l*e, 0); 63 | adder.add_edge(extra_dst, dst, p - l*w, 0); 64 | 65 | for (int i = 0; i < e; i++) { 66 | adder.add_edge(src, i, l, 0); 67 | adder.add_edge(extra, i, p, 0); 68 | } 69 | 70 | for (int i = e; i < e + w; i++) { 71 | adder.add_edge(i, dst, l, 0); 72 | adder.add_edge(i, extra_dst, p, 0); 73 | } 74 | 75 | for (int i = 0; i < m; i++) { 76 | int u, v, r; std::cin >> u >> v >> r; 77 | adder.add_edge(u, e + v, 1, r); 78 | } 79 | 80 | for (int i = 0; i < d; i++) { 81 | int u, v, r; std::cin >> u >> v >> r; 82 | adder.add_edge(danger, extra_dst, 1, r); 83 | } 84 | 85 | boost::successive_shortest_path_nonnegative_weights(g, src, dst); 86 | int cost = boost::find_flow_cost(g); 87 | 88 | int flow = 0; 89 | auto c_map = boost::get(boost::edge_capacity, g); 90 | auto rc_map = boost::get(boost::edge_residual_capacity, g); 91 | out_edge_it eg, eend; 92 | for(boost::tie(eg, eend) = boost::out_edges(boost::vertex(src, g), g); eg != eend; ++eg) { 93 | flow += c_map[*eg] - rc_map[*eg]; 94 | } 95 | 96 | if (flow == p) 97 | std::cout << cost << std::endl; 98 | else 99 | std::cout << "No schedule!" << std::endl; 100 | } 101 | 102 | int main() { 103 | std::ios_base::sync_with_stdio(false); 104 | 105 | int t; 106 | std::cin >> t; 107 | for (int i = 0; i < t; ++i) 108 | testcase(); 109 | } 110 | -------------------------------------------------------------------------------- /Week12/Rumpelstitskin/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | typedef boost::adjacency_list_traits traits; 17 | typedef boost::adjacency_list > > > > graph; 22 | 23 | typedef boost::graph_traits::edge_descriptor edge_desc; 24 | typedef boost::graph_traits::out_edge_iterator out_edge_it; 25 | 26 | class edge_adder { 27 | graph &G; 28 | 29 | public: 30 | explicit edge_adder(graph &G) : G(G) {} 31 | void add_edge(int from, int to, long capacity, long cost) { 32 | auto c_map = boost::get(boost::edge_capacity, G); 33 | auto r_map = boost::get(boost::edge_reverse, G); 34 | auto w_map = boost::get(boost::edge_weight, G); // new! 35 | const edge_desc e = boost::add_edge(from, to, G).first; 36 | const edge_desc rev_e = boost::add_edge(to, from, G).first; 37 | c_map[e] = capacity; 38 | c_map[rev_e] = 0; // reverse edge has no capacity! 39 | r_map[e] = rev_e; 40 | r_map[rev_e] = e; 41 | w_map[e] = cost; // new assign cost 42 | w_map[rev_e] = -cost; // new negative cost 43 | } 44 | }; 45 | 46 | void testcase() { 47 | int n, pg, ph, eg, eh, fg, fh, sg, sh; std::cin >> n >> pg >> ph >> eg >> eh >> fg >> fh >> sg >> sh; 48 | int src = pg + ph + 2*n, dst = src + 1; 49 | graph g(dst + 1); 50 | edge_adder adder(g); 51 | 52 | int max_pref = -1; 53 | std::vector preference(n); 54 | for (int i = 0; i < n; i++) { 55 | std::cin >> preference[i]; 56 | max_pref = std::max(max_pref, preference[i]); 57 | } 58 | 59 | adder.add_edge(src, 0, sg, 0); 60 | for (int i = 0; i < eg; i++) { 61 | int u, v, c; std::cin >> u >> v >> c; 62 | adder.add_edge(u, v, c, 0); 63 | } 64 | 65 | adder.add_edge(pg, dst, sh, 0); 66 | for (int i = 0; i < eh; i++) { 67 | int u, v, c; std::cin >> u >> v >> c; 68 | adder.add_edge(pg + v, pg + u, c, 0); 69 | } 70 | 71 | for (int i = 0; i < fg; i++) { 72 | int u, v, c; std::cin >> u >> v >> c; 73 | adder.add_edge(u, pg + ph + v, 1, 0); 74 | } 75 | 76 | for (int i = 0; i < fh; i++) { 77 | int u, v, c; std::cin >> u >> v >> c; 78 | adder.add_edge(pg + ph + n + v, pg + u, 1, 0); 79 | } 80 | 81 | for (int i = 0; i < n; i++) 82 | adder.add_edge(pg + ph + i, pg + ph + n + i, 1, max_pref - preference[i]); 83 | 84 | boost::successive_shortest_path_nonnegative_weights(g, src, dst); 85 | long cost = boost::find_flow_cost(g); 86 | 87 | auto c_map = boost::get(boost::edge_capacity, g); 88 | auto rc_map = boost::get(boost::edge_residual_capacity, g); 89 | out_edge_it e = boost::out_edges(boost::vertex(dst, g), g).first; 90 | 91 | long yarns = rc_map[*e] - c_map[*e]; 92 | long total_preference = yarns * max_pref - cost; 93 | std::cout << yarns << " " << total_preference << std::endl; 94 | } 95 | 96 | int main() { 97 | std::ios_base::sync_with_stdio(false); 98 | 99 | int t; 100 | std::cin >> t; 101 | for (int i = 0; i < t; ++i) 102 | testcase(); 103 | } 104 | -------------------------------------------------------------------------------- /PreviousYears/2022/CarSharing/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #define MAX_T 100000L 16 | #define MAX_P 100L 17 | 18 | typedef boost::adjacency_list_traits traits; 19 | typedef boost::adjacency_list > > > > graph; 24 | 25 | typedef boost::graph_traits::edge_descriptor edge_desc; 26 | typedef boost::graph_traits::out_edge_iterator out_edge_it; 27 | 28 | class edge_adder { 29 | graph &G; 30 | 31 | public: 32 | explicit edge_adder(graph &G) : G(G) {} 33 | void add_edge(int from, int to, long capacity, long cost) { 34 | auto c_map = boost::get(boost::edge_capacity, G); 35 | auto r_map = boost::get(boost::edge_reverse, G); 36 | auto w_map = boost::get(boost::edge_weight, G); // new! 37 | const edge_desc e = boost::add_edge(from, to, G).first; 38 | const edge_desc rev_e = boost::add_edge(to, from, G).first; 39 | c_map[e] = capacity; 40 | c_map[rev_e] = 0; // reverse edge has no capacity! 41 | r_map[e] = rev_e; 42 | r_map[rev_e] = e; 43 | w_map[e] = cost; // new assign cost 44 | w_map[rev_e] = -cost; // new negative cost 45 | } 46 | }; 47 | 48 | typedef struct Trip { 49 | int idx, depart, arrive, dst, p; 50 | } Trip; 51 | 52 | int n, s; 53 | std::vector l; 54 | std::vector> trips; 55 | 56 | void testcase() { 57 | std::cin >> n >> s; 58 | l = std::vector(s); 59 | trips = std::vector>(s, std::vector()); 60 | 61 | int src = n + s, snk = src + 1; 62 | graph g(snk + 1); 63 | edge_adder adder(g); 64 | 65 | long tot_l = 0; 66 | for (int i = 0; i < s; i++) { 67 | std::cin >> l[i]; 68 | tot_l += l[i]; 69 | } 70 | 71 | for (int i = 0; i < n; i++) { 72 | int si, ti, di, ai, pi; std::cin >> si >> ti >> di >> ai >> pi; 73 | trips[si - 1].push_back({i, di, ai, ti - 1, pi}); 74 | } 75 | 76 | for (int i = 0; i < s; i++) { 77 | auto& t = trips[i]; 78 | 79 | t.push_back({n + i, MAX_T, MAX_T + 1, -1, 0}); 80 | std::sort(t.begin(), t.end(), 81 | [](const Trip& t1, const Trip& t2) -> bool { 82 | return t1.depart < t2.depart; 83 | }); 84 | 85 | adder.add_edge(src, t[0].idx, l[i], MAX_P*t[0].depart); 86 | adder.add_edge(n + i, snk, tot_l, 0); 87 | 88 | for (int j = 1; j < t.size(); j++) 89 | adder.add_edge(t[j - 1].idx, t[j].idx, tot_l, MAX_P*(t[j].depart - t[j - 1].depart)); 90 | } 91 | 92 | for (int i = 0; i < s; i++) { 93 | for (const Trip& ti: trips[i]) { 94 | if (ti.dst == -1) 95 | continue; 96 | 97 | auto tj = std::lower_bound(trips[ti.dst].begin(), trips[ti.dst].end(), 98 | Trip({0, ti.arrive, 0, 0, 0}), 99 | [](const Trip& t1, const Trip& t2) -> bool { 100 | return t1.depart < t2.depart; 101 | }); 102 | 103 | if (tj != trips[ti.dst].end()) 104 | adder.add_edge(ti.idx, tj->idx, 1, MAX_P*(tj->depart - ti.depart) - ti.p); 105 | } 106 | } 107 | 108 | boost::successive_shortest_path_nonnegative_weights(g, src, snk); 109 | long cost = boost::find_flow_cost(g); 110 | 111 | std::cout << (tot_l*MAX_P*MAX_T - cost) << std::endl; 112 | } 113 | 114 | int main() { 115 | std::ios_base::sync_with_stdio(false); 116 | std::cin.tie(NULL); 117 | 118 | int t; 119 | std::cin >> t; 120 | for (int i = 0; i < t; ++i) 121 | testcase(); 122 | } 123 | -------------------------------------------------------------------------------- /Week14/OnHerMajestySecretService/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | typedef boost::adjacency_list // interior edge weight property 17 | > weighted_graph; 18 | typedef boost::property_map::type weight_map; 19 | typedef boost::graph_traits::edge_descriptor edge_desc; 20 | 21 | typedef boost::adjacency_list_traits traits; 22 | typedef boost::adjacency_list>>> graph; 26 | 27 | typedef traits::vertex_descriptor vertex_desc; 28 | typedef traits::edge_descriptor edge_desc; 29 | 30 | class edge_adder { 31 | graph &G; 32 | 33 | public: 34 | explicit edge_adder(graph &G) : G(G) {} 35 | 36 | void add_edge(int from, int to, long capacity) { 37 | auto c_map = boost::get(boost::edge_capacity, G); 38 | auto r_map = boost::get(boost::edge_reverse, G); 39 | const auto e = boost::add_edge(from, to, G).first; 40 | const auto rev_e = boost::add_edge(to, from, G).first; 41 | c_map[e] = capacity; 42 | c_map[rev_e] = 0; // reverse edge has no capacity! 43 | r_map[e] = rev_e; 44 | r_map[rev_e] = e; 45 | } 46 | }; 47 | 48 | void testcase() { 49 | int n, m, a, s, c, d; std::cin >> n >> m >> a >> s >> c >> d; 50 | std::vector> dists; 51 | weighted_graph g(n + a + s); 52 | 53 | for (int i = 0; i < m; i++) { 54 | char w; std::cin >> w; 55 | int x, y, z; std::cin >> x >> y >> z; 56 | boost::add_edge(x, y, z, g); 57 | 58 | if (w == 'L') 59 | boost::add_edge(y, x, z, g); 60 | } 61 | 62 | for (int i = 0; i < a; i++) { 63 | int p; std::cin >> p; 64 | boost::add_edge(n + i, p, 0, g); 65 | } 66 | 67 | for (int i = 0; i < s; i++) { 68 | int p; std::cin >> p; 69 | boost::add_edge(p, n + a + i, d, g); 70 | } 71 | 72 | for (int i = 0; i < a; i++) { 73 | std::vector dist_map(n + a + s); 74 | 75 | boost::dijkstra_shortest_paths( 76 | g, n + i, 77 | boost::distance_map(boost::make_iterator_property_map(dist_map.begin(), boost::get(boost::vertex_index, g))) 78 | ); 79 | 80 | for (int j = 0; j < s; j++) { 81 | int dist = dist_map[n + a + j]; 82 | 83 | if (dist != std::numeric_limits::max()) { 84 | dists.push_back({dist, i, a + j}); 85 | 86 | if (c == 2) 87 | dists.push_back({dist + d, i, a + s + j}); 88 | } 89 | } 90 | } 91 | 92 | std::sort(dists.begin(), dists.end()); 93 | 94 | int start = 0, end = dists.size(); 95 | while (start < end) { 96 | int mid = start + (end - start) / 2; 97 | int src = a + 2*s, dst = src + 1; 98 | graph g(dst + 1); 99 | edge_adder adder(g); 100 | 101 | for (int i = 0; i < a; i++) 102 | adder.add_edge(src, i, 1); 103 | 104 | for (int i = 0; i <= mid; i++) 105 | adder.add_edge(std::get<1>(dists[i]), std::get<2>(dists[i]), 1); 106 | 107 | for (int i = 0; i < s; i++) { 108 | adder.add_edge(a + i, dst, 1); 109 | adder.add_edge(a + s + i, dst, 1); 110 | } 111 | 112 | if (boost::push_relabel_max_flow(g, src, dst) == a) 113 | end = mid; 114 | else 115 | start = mid + 1; 116 | } 117 | 118 | std::cout << std::get<0>(dists[start]) << std::endl; 119 | } 120 | 121 | int main() { 122 | std::ios_base::sync_with_stdio(false); 123 | 124 | int t; 125 | std::cin >> t; 126 | for (int i = 0; i < t; ++i) 127 | testcase(); 128 | } 129 | -------------------------------------------------------------------------------- /PreviousYears/2022/TheHandTourney/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | typedef CGAL::Exact_predicates_inexact_constructions_kernel K; 20 | typedef std::size_t Index; 21 | typedef CGAL::Triangulation_vertex_base_with_info_2 Vb; 22 | typedef CGAL::Triangulation_face_base_2 Fb; 23 | typedef CGAL::Triangulation_data_structure_2 Tds; 24 | typedef CGAL::Delaunay_triangulation_2 Delaunay; 25 | 26 | typedef K::Point_2 P; 27 | typedef std::tuple Edge; 28 | typedef std::vector EdgeV; 29 | typedef std::pair IPoint; 30 | 31 | long n, k, f0, s0; 32 | 33 | bool solves(long f, const long s, EdgeV& edges) { 34 | boost::disjoint_sets_with_storage<> uf(n); 35 | long n_components = n; 36 | for (EdgeV::const_iterator e = edges.begin(); e != edges.end(); ++e) { 37 | if (std::get<2>(*e) >= s) 38 | break; 39 | 40 | Index c1 = uf.find_set(std::get<0>(*e)); 41 | Index c2 = uf.find_set(std::get<1>(*e)); 42 | 43 | if (c1 != c2) { 44 | uf.link(c1, c2); 45 | if (--n_components == 1) break; 46 | } 47 | } 48 | 49 | if (k == 1) 50 | return f <= n_components; 51 | 52 | std::vector counter(n, 0); 53 | std::vector bins(5, 0); 54 | for (int i = 0; i < n; i++) { 55 | int idx = uf.find_set(i); 56 | counter[uf.find_set(i)]++; 57 | } 58 | 59 | for (int i = 0; i < n_components; i++) 60 | bins[std::min(counter[i], (long)4)]++; 61 | 62 | if (k == 2) 63 | return f <= bins[1] / 2 + bins[2] + bins[3] + bins[4]; 64 | else if (k == 3) { 65 | if (bins[1] >= bins[2]) 66 | return f <= (bins[1] - bins[2]) / 3 + bins[2] + bins[3] + bins[4]; 67 | else 68 | return f <= bins[1] + bins[2] / 2 + bins[3] + bins[4]; 69 | } else { 70 | if (bins[1] == bins[3]) 71 | return f <= bins[2] / 2 + bins[3] + bins[4]; 72 | else if (bins[1] > bins[3]) { 73 | if (bins[2] % 2 && bins[1] >= 2) 74 | return f <= 1 + (bins[1] - 2 - bins[3]) / 4 + bins[2] / 2 + bins[3] + bins[4]; 75 | else 76 | return f <= (bins[1] - bins[3]) / 4 + bins[2] / 2 + bins[3] + bins[4]; 77 | } else 78 | return f <= bins[1] + bins[2] / 2 + (bins[3] + (bins[2] % 2) - bins[1]) / 2 + bins[4]; 79 | } 80 | } 81 | 82 | void testcase() { 83 | std::cin >> n >> k >> f0 >> s0; 84 | std::vector points(n); 85 | 86 | for (Index i = 0; i < n; ++i) { 87 | int x, y; std::cin >> x >> y; 88 | points[i] = {P(x, y), i}; 89 | } 90 | 91 | Delaunay t; 92 | t.insert(points.begin(), points.end()); 93 | 94 | EdgeV edges; 95 | edges.reserve(3*n); 96 | for (auto e = t.finite_edges_begin(); e != t.finite_edges_end(); ++e) { 97 | Index i1 = e->first->vertex((e->second+1)%3)->info(); 98 | Index i2 = e->first->vertex((e->second+2)%3)->info(); 99 | if (i1 > i2) std::swap(i1, i2); 100 | edges.emplace_back(i1, i2, t.segment(e).squared_length()); 101 | } 102 | 103 | std::sort(edges.begin(), edges.end(), 104 | [](const Edge& e1, const Edge& e2) -> bool { 105 | return std::get<2>(e1) < std::get<2>(e2); 106 | }); 107 | 108 | long start = 1, end = ((long)1<<50) + 1; 109 | while (start < end) { 110 | long mid = start + (end - start) / 2; 111 | 112 | if (solves(f0, mid, edges)) 113 | start = mid + 1; 114 | else 115 | end = mid; 116 | } 117 | 118 | std::cout << start - 1 << " "; 119 | 120 | start = 0; 121 | end = n + 1; 122 | while (start < end) { 123 | long mid = start + (end - start) / 2; 124 | 125 | if (solves(mid, s0, edges)) 126 | start = mid + 1; 127 | else 128 | end = mid; 129 | } 130 | 131 | std::cout << start - 1 << std::endl; 132 | } 133 | 134 | int main() { 135 | std::ios_base::sync_with_stdio(false); 136 | 137 | int t; 138 | std::cin >> t; 139 | for (int i = 0; i < t; ++i) 140 | testcase(); 141 | } 142 | -------------------------------------------------------------------------------- /Week07/GoldenEye/src/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | using K = CGAL::Exact_predicates_inexact_constructions_kernel; 17 | using P = K::Point_2; 18 | 19 | using Index = std::size_t; 20 | using Vb = CGAL::Triangulation_vertex_base_with_info_2; 21 | using Fb = CGAL::Triangulation_face_base_2; 22 | using Tds = CGAL::Triangulation_data_structure_2; 23 | using Delaunay = CGAL::Delaunay_triangulation_2; 24 | 25 | using Edge = std::tuple; 26 | using EdgeV = std::vector; 27 | using IPoint = std::pair; 28 | using Mission = std::pair; 29 | using MissionV = std::vector; 30 | 31 | long min_power(long n, EdgeV& edges, Delaunay& tr, MissionV& missions) { 32 | boost::disjoint_sets_with_storage<> uf(n); 33 | Index n_components = n; 34 | long min_p = 0; 35 | 36 | for (const auto& [s, t]: missions) { 37 | auto v = tr.nearest_vertex(s), w = tr.nearest_vertex(t); 38 | long p1 = 4*CGAL::squared_distance(s, v->point()), p2 = 4*CGAL::squared_distance(t, w->point()); 39 | min_p = std::max(min_p, std::max(p1, p2)); 40 | } 41 | 42 | EdgeV::const_iterator e = edges.begin(); 43 | for (const auto& [s, t]: missions) { 44 | auto v = tr.nearest_vertex(s)->info(), w = tr.nearest_vertex(t)->info(); 45 | 46 | if (uf.find_set(v) != uf.find_set(w)) { 47 | for (; e != edges.end() && n_components > 1; ++e) { 48 | Index c1 = uf.find_set(std::get<0>(*e)), c2 = uf.find_set(std::get<1>(*e)); 49 | 50 | if (c1 != c2) { 51 | uf.link(c1, c2); 52 | n_components--; 53 | min_p = std::max(min_p, (long)std::ceil(std::get<2>(*e))); 54 | 55 | if (uf.find_set(v) == uf.find_set(w)) 56 | break; 57 | } 58 | } 59 | } 60 | } 61 | 62 | return min_p; 63 | } 64 | 65 | void testcase() { 66 | long n, m, p; std::cin >> n >> m >> p; 67 | std::vector points(n); 68 | MissionV missions(m); 69 | MissionV possible; 70 | 71 | for (Index i = 0; i < (Index)n; i++) { 72 | long x, y; std::cin >> x >> y; 73 | points[i] = std::make_pair(P(x, y), i); 74 | } 75 | 76 | for (Index i = 0; i < (Index)m; i++) { 77 | long x0, y0, x1, y1; std::cin >> x0 >> y0 >> x1 >> y1; 78 | missions[i] = std::make_pair(P(x0, y0), P(x1, y1)); 79 | } 80 | 81 | Delaunay tr; 82 | tr.insert(points.begin(), points.end()); 83 | 84 | EdgeV edges; 85 | edges.reserve(3*n); 86 | for (auto e = tr.finite_edges_begin(); e != tr.finite_edges_end(); ++e) { 87 | Index i1 = e->first->vertex((e->second + 1) % 3)->info(); 88 | Index i2 = e->first->vertex((e->second + 2) % 3)->info(); 89 | 90 | if (i1 > i2) std::swap(i1, i2); 91 | edges.emplace_back(i1, i2, tr.segment(e).squared_length()); 92 | } 93 | 94 | std::sort(edges.begin(), edges.end(), 95 | [](const Edge& e1, const Edge& e2) -> bool { 96 | return std::get<2>(e1) < std::get<2>(e2); 97 | }); 98 | 99 | boost::disjoint_sets_with_storage<> uf(n); 100 | Index n_components = n; 101 | 102 | for (EdgeV::const_iterator e = edges.begin(); e != edges.end() && n_components > 1; ++e) { 103 | if (std::get<2>(*e) > p) 104 | break; 105 | 106 | Index c1 = uf.find_set(std::get<0>(*e)), c2 = uf.find_set(std::get<1>(*e)); 107 | if (c1 != c2) { 108 | uf.link(c1, c2); 109 | n_components--; 110 | } 111 | } 112 | 113 | for (const auto& [s, t]: missions) { 114 | auto v = tr.nearest_vertex(s), w = tr.nearest_vertex(t); 115 | long p1 = 4*CGAL::squared_distance(s, v->point()), p2 = 4*CGAL::squared_distance(t, w->point()); 116 | 117 | if (p1 <= p && p2 <= p) { 118 | if (uf.find_set(v->info()) == uf.find_set(w->info())) { 119 | possible.push_back(std::make_pair(s, t)); 120 | std::cout << "y"; 121 | } else 122 | std::cout << "n"; 123 | } 124 | else 125 | std::cout << "n"; 126 | } 127 | 128 | std::cout << std::endl << min_power(n, edges, tr, missions); 129 | std::cout << std::endl << min_power(n, edges, tr, possible) << std::endl; 130 | } 131 | 132 | int main() { 133 | std::ios_base::sync_with_stdio(false); 134 | 135 | int t; 136 | std::cin >> t; 137 | for (int i = 0; i < t; ++i) 138 | testcase(); 139 | } 140 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Algorithms Lab - Fall 2023 2 | Code Expert exercises from the Algorithms Lab course at ETH Zürich. 3 | 4 | ## Setup 5 | A modified version of the ```algolabVS.sh``` script is used for my specific setup, hence no portability 6 | is guaranteed. The script is meant to be used as specified by its documentation. 7 | 8 | ## Problem Set 9 | 10 | | Solution | Week | Type | 11 | | --------------------------------------------------------------------------------------- | --------- | ------------------------ | 12 | | [build_the_sum.cpp](Week01/BuildTheSum/src/algorithm.cpp) | Week 1 | --- | 13 | | [dominoes.cpp](Week01/Dominoes/src/algorithm.cpp) | Week 1 | --- | 14 | | [even_pairs.cpp](Week01/EvenPairs/src/algorithm.cpp) | Week 1 | Combinatorics | 15 | | [even_matrices.cpp](Week01/EvenMatrices/src/algorithm.cpp) | Week 1 | Combinatorics | 16 | | [deck_of_cards.cpp](Week02/DeckOfCards/src/algorithm.cpp) | POTW 2 | SW | 17 | | [burning_coins.cpp](Week02/BurningCoins/src/algorithm.cpp) | Week 2 | DP | 18 | | [beach_bars.cpp](Week02/BeachBars/src/algorithm.cpp) | Week 2 | SW | 19 | | [the_great_game.cpp](Week02/TheGreatGame/src/algorithm.cpp) | Week 2 | Minimax + DP | 20 | | [lord_voldemort.cpp](Week02/LordVoldemort/src/algorithm.cpp) | Week 2 | DP + Precompute | 21 | | [james_bond_sovereigns.cpp](Week03/JamesBondSovereigns/src/algorithm.cpp) | POTW 3 | DP | 22 | | [first_steps_bgl.cpp](Week03/FirstStepsBGL/src/algorithm.cpp) | Week 3 | Dijkstra + MST | 23 | | [buddy_selection.cpp](Week03/BuddySelection/src/algorithm.cpp) | Week 3 | Maximum Matching | 24 | | [important_bridges.cpp](Week03/ImportantBridges/src/algorithm.cpp) | Week 3 | Biconnected Components | 25 | | [ant_challenge.cpp](Week03/AntChallenge/src/algorithm.cpp) | Week 3 | Dijkstra + Prim MST | 26 | | [iron_islands.cpp](Week04/IronIslands/src/algorithm.cpp) | POTW 4 | SW | 27 | | [hit.cpp](Week04/Hit/src/algorithm.cpp) | Week 4 | CGAL geometry | 28 | | [first_hit.cpp](Week04/FirstHit/src/algorithm.cpp) | Week 4 | "Smarter" Hit | 29 | | [antenna.cpp](Week04/Antenna/src/algorithm.cpp) | Week 4 | Min Circle | 30 | | [hiking_maps.cpp](Week04/HikingMaps/src/algorithm.cpp) | Week 4 | Orientations | 31 | | [planet_express.cpp](Week05/PlanetExpress/src/algorithm.cpp) | POTW 5 | SCC + Dijkstra | 32 | | [moving_books.cpp](Week05/MovingBooks/src/algorithm.cpp) | Week 5 | Greedy | 33 | | [asterix_the_gaul.cpp](Week05/AsterixTheGaul/src/algorithm.cpp) | Week 5 | Split&List + BS | 34 | | [severus_snape.cpp](Week05/SeverusSnape/src/algorithm.cpp) | Week 5 | Greedy + DP | 35 | | [boats.cpp](Week05/Boats/src/algorithm.cpp) | Week 5 | Greedy | 36 | | [motorcycles.cpp](Week06/Motorcycles/src/algorithm.cpp) | POTW 6 | CGAL geometry | 37 | | [tiles.cpp](Week06/Tiles/src/algorithm.cpp) | Week 6 | MaxFlow | 38 | | [london.cpp](Week06/London/src/algorithm.cpp) | Week 6 | MaxFlow | 39 | | [coin_tossing_tournament.cpp](Week06/CoinTossingTournament/src/algorithm.cpp) | Week 6 | MaxFlow | 40 | | [knights.cpp](Week06/Knights/src/algorithm.cpp) | Week 6 | MaxFlow | 41 | | [octopussy.cpp](Week07/Octopussy/src/algorithm.cpp) | POTW 7 | Greedy + DFS | 42 | | [bistro.cpp](Week07/Bistro/src/algorithm.cpp) | Week 7 | Delaunay | 43 | | [germs.cpp](Week07/Germs/src/algorithm.cpp) | Week 7 | Delaunay | 44 | | [h1n1.cpp](Week07/H1N1/src/algorithm.cpp) | Week 7 | Delaunay + PrioQueue | 45 | | [goldeneye.cpp](Week07/GoldenEye/src/algorithm.cpp) | Week 7 | Delaunay + UF (EMST-like)| 46 | | [kingdom_defence.cpp](Week08/KingdomDefence/src/algorithm.cpp) | POTW 8 | Supply/Demand MaxFlow | 47 | | [what_is_the_maximum.cpp](Week08/WhatIsTheMaximum/src/algorithm.cpp) | Week 8 | CGAL LP | 48 | | [suez.cpp](Week08/Suez/src/algorithm.cpp) | Week 8 | CGAL LP | 49 | | [inball.cpp](Week08/Inball/src/algorithm.cpp) | Week 8 | CGAL LP + LinAlg | 50 | | [diet.cpp](Week08/Diet/src/algorithm.cpp) | Week 8 | CGAL LP | 51 | | [idefix.cpp](Week09/Idefix/src/algorithm.cpp) | POTW 9 | Delaunay + UF + BS | 52 | | [canteen.cpp](Week09/Canteen/src/algorithm.cpp) | Week 9 | MinCostMaxFlow | 53 | | [placing_knights.cpp](Week09/PlacingKnights/src/algorithm.cpp) | Week 9 | Bipartite MaxIS | 54 | | [real_estate_market.cpp](Week09/RealEstateMarket/src/algorithm.cpp) | Week 9 | MinCostMaxFlow | 55 | | [algocoon.cpp](Week09/Algocoon/src/algorithm.cpp) | Week 9 | MinCut | 56 | | [lannister.cpp](Week10/Lannister/src/algorithm.cpp) | POTW 10 | CGAL LP | 57 | | [san_francisco.cpp](Week10/SanFrancisco/src/algorithm.cpp) | Week 10 | DP | 58 | | [rubeus_hagrid.cpp](Week10/RubeusHagrid/src/algorithm.cpp) | Week 10 | Greedily Sorted DFS | 59 | | [surveillance_photograph.cpp](Week10/SurveillancePhotograph/src/algorithm.cpp) | Week 10 | MaxFlow | 60 | | [clues.cpp](Week10/Clues/src/algorithm.cpp) | Week 10 | CC + Bipartite | 61 | | [india.cpp](Week11/India/src/algorithm.cpp) | POTW 11 | MinCostMaxFlow + BS | 62 | | [asterix_chariot_race.cpp](Week11/AsterixChariotRace/src/algorithm.cpp) | Week 11 | DP | 63 | | [dean_thomas.cpp](Week11/DeanThomas/src/algorithm.cpp) | Week 11 | Delaunay + PrioQueue | 64 | | [legions.cpp](Week11/Legions/src/algorithm.cpp) | Week 11 | CGAL LP + LinAlg | 65 | | [phantom_menace.cpp](Week11/PhantomMenace/src/algorithm.cpp) | Week 11 | MinimumCut | 66 | | [pied_piper.cpp](Week12/PiedPiper/src/algorithm.cpp) | POTW 12 | DP | 67 | | [new_york.cpp](Week12/NewYork/src/algorithm.cpp) | Week 12 | SW + PrioQ | 68 | | [return_of_the_jedi.cpp](Week12/ReturnOfTheJedi/src/algorithm.cpp) | Week 12 | 2nd-best MST | 69 | | [rumpelstitskin.cpp](Week12/Rumpelstitskin/src/algorithm.cpp) | Week 12 | Max Weighted Matching | 70 | | [world_cup.cpp](Week12/WorldCup/src/algorithm.cpp) | Week 12 | CGAL LP + Delaunay | 71 | | [schneewittchen.cpp](Week13/Schneewittchen/src/algorithm.cpp) | POTW 13 | CGAL LP + DFS | 72 | | [augean_stables.cpp](Week13/AugeanStables/src/algorithm.cpp) | Week 13 | BS + LP (85/100) | 73 | | [casino_royale.cpp](Week13/CasinoRoyale/src/algorithm.cpp) | Week 13 | MinCostMaxFlow | 74 | | [dhl.cpp](Week13/DHL/src/algorithm.cpp) | Week 13 | DP | 75 | | [fighting_pits_of_meeren.cpp](Week13/FightingPitsOfMeeren/src/algorithm.cpp) | Week 13 | | 76 | | [on_her_majesty_secret_service.cpp](Week14/OnHerMajestySecretService/src/algorithm.cpp) | POTW 14 | Dijkstra + BS + MaxFlow | 77 | 78 | ## Exam 79 | These are my solutions for the exam problems. Since from the exam paper I was only able to retrieve 80 | the sample tests, there is no correctness guarantee on these rewrites. The original versions scored 81 | full points, save for **Croquet** for which I can only guarantee a *75/100* score. 82 | 83 | Overall, the exam was much simpler than the general course content, and on top of the guaranteed 84 | repeat problems, **MadTeaParty** was also a near clone of **PlacingKnights**. The most challenging problem 85 | was by far **Croquet**, although it was possible to pick up a lot of points through individual cases. 86 | 87 | ### Part 1 88 | | Solution | Type | 89 | | ------------------------------------------------------------------------------------------- | ------------------------ | 90 | | [croquet.cpp](Exam/P1/Croquet/src/algorithm.cpp) | Delaunay + Dijkstra | 91 | | [queen_of_hearts.cpp](Exam/P1/QueenOfHearts/src/algorithm.cpp) | Dijkstra + MinimumCut | 92 | | [down_the_rabbit_hole.cpp](Week10/RubeusHagrid/src/algorithm.cpp) | *RubeusHagrid Clone* | 93 | 94 | 95 | ### Part 2 96 | | Solution | Type | 97 | | ------------------------------------------------------------------------------------------- | ------------------------ | 98 | | [rabbit_clan.cpp](Exam/P2/RabbitClan/src/algorithm.cpp) | DP | 99 | | [mad_tea_party.cpp](Exam/P2/MadTeaParty/src/algorithm.cpp) | Bipartite MaxIS | 100 | | [chronosphere.cpp](Week11/Legions/src/algorithm.cpp) | *Legions Clone* | 101 | 102 | 103 | ## Previous Years 104 | This is a collection of problems for the previous years I used to prepare for the exam. 105 | 106 | ### 2022 107 | 108 | | Solution | Type | 109 | | ------------------------------------------------------------------------------------------- | ------------------------ | 110 | | [asterix_in_switzerland.cpp](PreviousYears/2022/AsterixInSwitzerland/src/algorithm.cpp) | MaxFlow | 111 | | [car_sharing.cpp](PreviousYears/2022/CarSharing/src/algorithm.cpp) | MinCostMaxFlow | 112 | | [empire_strikes_back.cpp](PreviousYears/2022/EmpireStrikesBack/src/algorithm.cpp) | CGAL LP + Delaunay | 113 | | [evolution.cpp](PreviousYears/2022/Evolution/src/algorithm.cpp) | BS | 114 | | [fleet_race.cpp](PreviousYears/2022/FleetRace/src/algorithm.cpp) | MinCostMaxFlow | 115 | | [light_the_stage.cpp](PreviousYears/2022/LightTheStage/src/algorithm.cpp) | BS + Delaunay | 116 | | [ludo_bagman.cpp](PreviousYears/2022/LudoBagman/src/algorithm.cpp) | MinCostMaxFlow | 117 | | [marathon.cpp](PreviousYears/2022/Marathon/src/algorithm.cpp) | MultiPath Dijkstra + MF | 118 | | [revenge_of_the_sith.cpp](PreviousYears/2022/RevengeOfTheSith/src/algorithm.cpp) | BS(really cool) + UF | 119 | | [the_hand_tourney.cpp](PreviousYears/2022/TheHandTourney/src/algorithm.cpp) | BS + UF (hardcoded ifs) | 120 | | [tracking.cpp](PreviousYears/2022/Tracking/src/algorithm.cpp) | Dijkstra | 121 | --------------------------------------------------------------------------------