├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── README.md ├── official_solutions ├── algocoon.pdf ├── buddy-selection.pdf ├── car_sharing.pdf ├── even_matrices.pdf ├── firsthit.pdf ├── germs.pdf ├── hiking-maps.pdf ├── inball.pdf ├── moving_books.pdf ├── olympicgames.pdf ├── russia.pdf ├── secret_service.pdf └── the_great_game.pdf ├── src ├── algocoon.cpp ├── ant_challenge.cpp ├── antenna.cpp ├── asterix_the_gaul.cpp ├── attack_of_the_clones.cpp ├── beach_bars.cpp ├── bistro.cpp ├── boats.cpp ├── buddy_selection.cpp ├── build_the_sum.cpp ├── burning_coins.cpp ├── carsharing.cpp ├── casino.cpp ├── chariot_race.cpp ├── clues.cpp ├── deck_of_cards.cpp ├── defensive_line.cpp ├── diet.cpp ├── dominoes.cpp ├── even_matrices.cpp ├── even_pairs.cpp ├── evolution.cpp ├── first_hit.cpp ├── first_steps.cpp ├── fleetrace.cpp ├── germs.cpp ├── h1n1.cpp ├── hand.cpp ├── hiking_maps.cpp ├── hit.cpp ├── hongkong.cpp ├── idefix.cpp ├── important_bridges.cpp ├── inball.cpp ├── india.cpp ├── iron_islands.cpp ├── kingdom_defence.cpp ├── knights.cpp ├── lannister.cpp ├── legions.cpp ├── lestrade.cpp ├── marathon.cpp ├── maximizeit.cpp ├── meereen.cpp ├── motorcycles.cpp ├── moving_books.cpp ├── moving_books_binary_search.cpp ├── new_york.cpp ├── octopussy.cpp ├── placing_knights.cpp ├── punch.cpp ├── radiation.cpp ├── real_estate.cpp ├── return_of_the_jedi.cpp ├── russia_official_solution.cpp ├── san_francisco.cpp ├── search_snippets.cpp ├── secret_service.cpp ├── shopping_trip.cpp ├── sith.cpp ├── surveillance.cpp ├── switzerland.cpp ├── the_great_game.cpp ├── tiles.cpp ├── tracking.cpp └── worldcup.cpp └── tasks ├── algocoon.pdf ├── ant_challenge.pdf ├── antenna.pdf ├── asterix_the_gaul.pdf ├── attack_of_the_clones.pdf ├── beach_bars.pdf ├── bistro.pdf ├── boats.pdf ├── buddies.pdf ├── build_the_sum.pdf ├── burning_coins.pdf ├── carsharing.pdf ├── casino.pdf ├── chariot_race.pdf ├── clues.pdf ├── deck_of_cards.pdf ├── defensive_line.pdf ├── diet.pdf ├── dominoes.pdf ├── even_matrices.pdf ├── even_pairs.pdf ├── evolution.pdf ├── first_hit.pdf ├── first_steps.pdf ├── fleetrace.pdf ├── germs.pdf ├── h1n1.pdf ├── hand.pdf ├── hiking_maps.pdf ├── hit.pdf ├── hongkong.pdf ├── idefix.pdf ├── importantbridges.pdf ├── inball.pdf ├── india.pdf ├── iron_islands.pdf ├── kingdom_defence.pdf ├── knights.pdf ├── lannister.pdf ├── legions.pdf ├── lestrade.pdf ├── marathon.pdf ├── maximizeit.pdf ├── meereen.pdf ├── motorcycles.pdf ├── moving_books.pdf ├── new_york.pdf ├── octopussy.pdf ├── placing_knights.pdf ├── punch.pdf ├── radiation.pdf ├── real_estate.pdf ├── return_of_the_jedi.pdf ├── russia.pdf ├── san francisco.pdf ├── search_snippets.pdf ├── secret_service.pdf ├── shopping_trip.pdf ├── sith.pdf ├── surveillance.pdf ├── switzerland.pdf ├── the_great_game.pdf ├── tiles.pdf ├── tracking.pdf └── worldcup.pdf /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | .idea 35 | build 36 | cmake-build-debug 37 | cmake-build-release 38 | .vscode/settings.json 39 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | project(algolab) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | 6 | find_package(CGAL) 7 | 8 | 9 | # Week 1 10 | add_executable(build_the_sum src/build_the_sum.cpp) 11 | add_executable(dominoes src/dominoes.cpp) 12 | add_executable(even_pairs src/even_pairs.cpp) 13 | add_executable(even_matrices src/even_matrices.cpp) 14 | 15 | 16 | # Week 2 17 | add_executable(burning_coins src/burning_coins.cpp) 18 | add_executable(the_great_game src/the_great_game.cpp) 19 | add_executable(beach_bars src/beach_bars.cpp) 20 | add_executable(search_snippets src/search_snippets.cpp) 21 | 22 | 23 | # Week 3 24 | add_executable(hit src/hit.cpp) 25 | add_executable(first_hit src/first_hit.cpp) 26 | add_executable(antenna src/antenna.cpp) 27 | add_executable(hiking_maps src/hiking_maps.cpp) 28 | 29 | target_link_libraries(hit CGAL::CGAL) 30 | target_link_libraries(first_hit CGAL::CGAL) 31 | target_link_libraries(antenna CGAL::CGAL) 32 | target_link_libraries(hiking_maps CGAL::CGAL) 33 | 34 | 35 | # Week 4 36 | add_executable(ant_challenge src/ant_challenge.cpp) 37 | add_executable(important_bridges src/important_bridges.cpp) 38 | add_executable(first_steps src/first_steps.cpp) 39 | add_executable(buddy_selection src/buddy_selection.cpp) 40 | 41 | 42 | # Week 5 43 | add_executable(attack_of_the_clones src/attack_of_the_clones.cpp) 44 | add_executable(san_francisco src/san_francisco.cpp) 45 | add_executable(boats src/boats.cpp) 46 | add_executable(asterix_the_gaul src/asterix_the_gaul.cpp) 47 | 48 | 49 | # Week 6 50 | add_executable(shopping_trip src/shopping_trip.cpp) 51 | add_executable(tiles src/tiles.cpp) 52 | add_executable(knights src/knights.cpp) 53 | add_executable(kingdom_defence src/kingdom_defence.cpp) 54 | 55 | 56 | # Week 7 57 | add_executable(maximizeit src/maximizeit.cpp) 58 | add_executable(diet src/diet.cpp) 59 | add_executable(inball src/inball.cpp) 60 | add_executable(radiation src/radiation.cpp) 61 | 62 | target_link_libraries(maximizeit CGAL::CGAL) 63 | target_link_libraries(diet CGAL::CGAL) 64 | target_link_libraries(inball CGAL::CGAL) 65 | target_link_libraries(radiation CGAL::CGAL) 66 | 67 | 68 | # Week 8 69 | add_executable(bistro src/bistro.cpp) 70 | add_executable(germs src/germs.cpp) 71 | add_executable(h1n1 src/h1n1.cpp) 72 | add_executable(clues src/clues.cpp) 73 | 74 | target_link_libraries(bistro CGAL::CGAL) 75 | target_link_libraries(germs CGAL::CGAL) 76 | target_link_libraries(h1n1 CGAL::CGAL) 77 | target_link_libraries(clues CGAL::CGAL) 78 | 79 | 80 | # Week 9 81 | add_executable(real_estate src/real_estate.cpp) 82 | add_executable(placing_knights src/placing_knights.cpp) 83 | add_executable(algocoon src/algocoon.cpp) 84 | add_executable(casino src/casino.cpp) 85 | 86 | 87 | # Week 10 88 | add_executable(chariot_race src/chariot_race.cpp) 89 | add_executable(switzerland src/switzerland.cpp) 90 | add_executable(new_york src/new_york.cpp) 91 | add_executable(worldcup src/worldcup.cpp) 92 | 93 | target_link_libraries(worldcup CGAL::CGAL) 94 | 95 | 96 | # Week 11 97 | add_executable(return_of_the_jedi src/return_of_the_jedi.cpp) 98 | add_executable(lestrade src/lestrade.cpp) 99 | add_executable(hand src/hand.cpp) 100 | add_executable(meereen src/meereen.cpp) 101 | 102 | target_link_libraries(hand CGAL::CGAL) 103 | target_link_libraries(lestrade CGAL::CGAL) 104 | 105 | 106 | # Week 12 107 | add_executable(moving_books src/moving_books.cpp) 108 | add_executable(carsharing src/carsharing.cpp) 109 | add_executable(india src/india.cpp) 110 | add_executable(hongkong src/hongkong.cpp) 111 | 112 | target_link_libraries(hongkong CGAL::CGAL) 113 | 114 | 115 | # Week 13 116 | add_executable(evolution src/evolution.cpp) 117 | add_executable(marathon src/marathon.cpp) 118 | add_executable(punch src/punch.cpp) 119 | add_executable(sith src/sith.cpp) 120 | 121 | target_link_libraries(sith CGAL::CGAL) 122 | 123 | 124 | # Problems of the week 125 | add_executable(deck_of_cards src/deck_of_cards.cpp) 126 | add_executable(russia src/russia_official_solution.cpp) 127 | add_executable(defensive_line src/defensive_line.cpp) 128 | add_executable(motorcycles src/motorcycles.cpp) 129 | add_executable(tracking src/tracking.cpp) 130 | add_executable(octopussy src/octopussy.cpp) 131 | add_executable(surveillance src/surveillance.cpp) 132 | add_executable(legions src/legions.cpp) 133 | add_executable(idefix src/idefix.cpp) 134 | add_executable(fleetrace src/fleetrace.cpp) 135 | add_executable(iron_islands src/iron_islands.cpp) 136 | add_executable(lannister src/lannister.cpp) 137 | add_executable(secret_service src/secret_service.cpp) 138 | 139 | target_link_libraries(motorcycles CGAL::CGAL) 140 | target_link_libraries(legions CGAL::CGAL) 141 | target_link_libraries(idefix CGAL::CGAL) -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Daniel Sparber 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Algorithms Lab 2020 2 | 3 | ## Build 4 | 5 | ```shell script 6 | mkdir build 7 | cd build 8 | cmake .. 9 | make -j8 10 | ``` 11 | 12 | ## Problems 13 | 14 | | Task | Implementation | Score | Week | Topics | 15 | | ----------------------------------------------------- | --------------------------------------------------------- | --------- | --------- | ------------- | 16 | | [Build the Sum](tasks/build_the_sum.pdf) | [build_the_sum.cpp](src/build_the_sum.cpp) | 100 | Week 1 | --- | 17 | | [Dominoes](tasks/dominoes.pdf) | [dominoes.cpp](src/dominoes.cpp) | 100 | Week 1 | --- | 18 | | [Even pairs](tasks/deck_of_cards.pdf) | [even_pairs.cpp](src/even_pairs.cpp) | 100 | Week 1 | --- | 19 | | [Even Matrices](tasks/even_matrices.pdf) | [even_matrices.cpp](src/even_matrices.cpp) | 100 | Week 1 | --- | 20 | | [Deck of Cards](tasks/deck_of_cards.pdf) | [deck_of_cards.cpp](src/deck_of_cards.cpp) | 100 | Week 2* | DP | 21 | | [Burning Coins](tasks/burning_coins.pdf) | [burning_coins.cpp](src/burning_coins.cpp) | 100 | Week 2 | DP | 22 | | [The Great Game](tasks/the_great_game.pdf) | [the_great_game.cpp](src/the_great_game.cpp) | 100 | Week 2 | DP | 23 | | [Beach Bars](tasks/beach_bars.pdf) | [beach_bars.cpp](src/beach_bars.cpp) | 100 | Week 2 | SW | 24 | | [Search Snippets](tasks/search_snippets.pdf) | [search_snippets.cpp](src/search_snippets.cpp) | 100 | Week 2 | SW | 25 | | [Russia](tasks/russia.pdf) | [russia.cpp](src/russia_official_solution.cpp) | 100 | Week 3* | DP | 26 | | [Hit](tasks/hit.pdf) | [hit.cpp](src/hit.cpp) | 100 | Week 3 | Geo | 27 | | [First Hit](tasks/first_hit.pdf) | [first_hit.cpp](src/first_hit.cpp) | 100 | Week 3 | Geo | 28 | | [Antenna](tasks/antenna.pdf) | [antenna.cpp](src/antenna.cpp) | 100 | Week 3 | Geo | 29 | | [Hiking Maps](tasks/hiking_maps.pdf) | [hiking_maps.cpp](src/hiking_maps.cpp) | 100 | Week 3 | Geo | 30 | | [Defensive Line](tasks/defensive_line.pdf) | [defensive_line.cpp](src/defensive_line.cpp) | 100 | Week 4* | SW & DP | 31 | | [First Steps with BGL](tasks/first_steps.pdf) | [first_steps.cpp](src/first_steps.cpp) | 100 | Week 4 | SP | 32 | | [Ant Challenge](tasks/ant_challenge.pdf) | [ant_challenge.cpp](src/ant_challenge.cpp) | 100 | Week 4 | MST & SP | 33 | | [Buddy Selection](tasks/buddy_selection.pdf) | [buddy_selection.cpp](src/buddy_selection.cpp) | 100 | Week 4 | MM | 34 | | [Important Bridges](tasks/important_bridges.pdf) | [important_bridges.cpp](src/important_bridges.cpp) | 100 | Week 4 | 2CC | 35 | | [Motorcycles](tasks/motorcycles.pdf) | [motorcycles.cpp](src/motorcycles.cpp) | 100 | Week 5* | Geo | 36 | | [Boats](tasks/boats.pdf) | [boats.cpp](src/boats.cpp) | 100 | Week 5 | Greedy | 37 | | [Attack of the Clones](tasks/attack_of_the_clones.pdf)| [attack_of_the_clones.cpp](src/attack_of_the_clones.cpp) | 100 | Week 5 | Greedy | 38 | | [San Francisco](tasks/san_francisco.pdf) | [san_francisco.cpp](src/san_francisco.cpp) | 100 | Week 5 | DP | 39 | | [Asterix the Gaul](tasks/asterix_the_gaul.pdf) | [asterix_the_gaul.cpp](src/asterix_the_gaul.cpp) | 100 | Week 5 | BS & SL | 40 | | [Tracking](tasks/tracking.pdf) | [tracking.cpp](src/tracking.cpp) | 100 | Week 6* | SP | 41 | | [Shopping Trip](tasks/shopping_trip.pdf) | [shopping_trip.cpp](src/shopping_trip.cpp) | 100 | Week 6 | MF | 42 | | [Knights](tasks/knights.pdf) | [knights.cpp](src/knights.cpp) | 100 | Week 6 | MF | 43 | | [Tiles](tasks/tiles.pdf) | [tiles.cpp](src/tiles.cpp) | 100 | Week 6 | MF | 44 | | [Kingdom Defence](tasks/kingdom_defence.pdf) | [kingdom_defence.cpp](src/kingdom_defence.cpp) | 100 | Week 6 | MF | 45 | | [Octopussy](tasks/octopussy.pdf) | [octopussy.cpp](src/octopussy.cpp) | 100 | Week 7* | DP-like | 46 | | [Maximize it](tasks/maximizeit.pdf) | [maximizeit.cpp](src/maximizeit.cpp) | 100 | Week 7 | LP | 47 | | [Diet](tasks/diet.pdf) | [diet.cpp](src/diet.cpp) | 100 | Week 7 | LP | 48 | | [Inball](tasks/inball.pdf) | [inball.cpp](src/inball.cpp) | 100 | Week 7 | LP | 49 | | [Radiation](tasks/radiation.pdf) | [radiation.cpp](src/radiation.cpp) | 100 | Week 7 | LP | 50 | | [Surveillance](tasks/surveillance.pdf) | [surveillance.cpp](src/surveillance.cpp) | 100 | Week 8* | MF | 51 | | [Bistro](tasks/bistro.pdf) | [bistro.cpp](src/bistro.cpp) | 100 | Week 8 | DT | 52 | | [Germs](tasks/germs.pdf) | [germs.cpp](src/germs.cpp) | 100 | Week 8 | DT | 53 | | [H1N1](tasks/h1n1.pdf) | [h1n1.cpp](src/h1n1.cpp) | 100 | Week 8 | DT, MST | 54 | | [Clues](tasks/clues.pdf) | [clues.cpp](src/clues.cpp) | 100 | Week 8 | DT, 2C, CC | 55 | | [Legions](tasks/legions.pdf) | [legions.cpp](src/legions.cpp) | 100 | Week 9* | LP | 56 | | [Casino Royale](tasks/casino.pdf) | [casino.cpp](src/casino.cpp) | 100 | Week 9 | MCMF | 57 | | [Real Estate](tasks/real_estate.pdf) | [real_estate.cpp](src/real_estate.cpp) | 100 | Week 9 | MCMF | 58 | | [Algocoon](tasks/algocoon.pdf) | [algocoon.cpp](src/algocoon.cpp) | 100 | Week 9 | MC | 59 | | [Placing Knights](tasks/placing_knights.pdf) | [placing_knights.cpp](src/placing_knights.cpp) | 100 | Week 9 | MaxIS | 60 | | [Idefix](tasks/idefix.pdf) | [idefix.cpp](src/idefix.cpp) | 100 | Week 10* | DT & UF | 61 | | [Chariot Race](tasks/chariot_race.pdf) | [chariot_race.cpp](src/chariot_race.cpp) | 100 | Week 10 | DP-like | 62 | | [New York](tasks/new_york.pdf) | [new_york.cpp](src/new_york.cpp) | 100 | Week 10 | SW over tree | 63 | | [Worldcup](tasks/worldcup.pdf) | [worldcup.cpp](src/worldcup.cpp) | 100 | Week 10 | LP & DT | 64 | | [Switzerland](tasks/switzerland.pdf) | [switzerland.cpp](src/switzerland.cpp) | 100 | Week 10 | MF | 65 | | [Fleet Race](tasks/fleetrace.pdf) | [fleetrace.cpp](src/fleetrace.cpp) | 100 | Week 11* | MCMF | 66 | | [Return of the Jedi](tasks/return_of_the_jedi.pdf) | [return_of_the_jedi.cpp](src/return_of_the_jedi.cpp) | 100 | Week 11 | 2nd best MST | 67 | | [Lestrade](tasks/lestrade.pdf) | [lestrade.cpp](src/lestrade.cpp) | 100 | Week 11 | LP & DT | 68 | | [Hand](tasks/hand.pdf) | [hand.cpp](src/hand.cpp) | 100 | Week 11 | DT, UF | 69 | | [Meereen](tasks/meereen.pdf) | [meereen.cpp](src/meereen.cpp) | 100 | Week 11 | DP | 70 | | [Iron Islands](tasks/iron_islands.pdf) | [iron_islands.cpp](src/iron_islands.cpp) | 100 | Week 12* | SW | 71 | | [Car Sharing](tasks/carsharing.pdf) | [carsharing.cpp](src/carsharing.cpp) | 100 | Week 12 | MCMF | 72 | | [Hong Kong](tasks/hongkong.pdf) | [hongkong.cpp](src/hongkong.cpp) | 100 | Week 12 | DT, SP | 73 | | [India](tasks/india.pdf) | [india.cpp](src/india.cpp) | 100 | Week 12 | BS & MCMF | 74 | | [Moving Books](tasks/moving_books.pdf) | [moving_books.cpp](src/moving_books.cpp) | 100 | Week 12 | Greedy | 75 | | [Lannister](tasks/lannister.pdf) | [lannister.cpp](src/lannister.cpp) | 100 | Week 13* | LP | 76 | | [Evolution](tasks/evolution.pdf) | [evolution.cpp](src/evolution.cpp) | 100 | Week 13 | DFS & BS | 77 | | [Marathon](tasks/marathon.pdf) | [marathon.cpp](src/marathon.cpp) | 100 | Week 13 | SP & MF | 78 | | [Punch](tasks/punch.pdf) | [punch.cpp](src/punch.cpp) | 100 | Week 13 | DP | 79 | | [Sith](tasks/sith.pdf) | [sith.cpp](src/sith.cpp) | 100 | Week 13 | DT & BS | 80 | | [Secret Service](tasks/secret_service.pdf) | [secret_service.cpp](src/secret_service.cpp) | 100 | Week 14* | BS & MF | 81 | 82 | 83 | ### Legend 84 | - *: This was a "Problem of the Week" 85 | - 2C: 2-Coloring / Bipartition 86 | - 2CC: 2-Connected Components / Biconnected Components 87 | - BS: Binary Search 88 | - CC: Connected Components 89 | - DFS: Depth First Search 90 | - DP: Dynamic Programming 91 | - DT: Delaunay Triangulation 92 | - Geo: Geometric 93 | - LP: Linear Programming 94 | - MC: Min. Cut 95 | - MCMF: Min. Cost Max. Flow 96 | - MF: Max. Flow 97 | - MM: Maximal Matching 98 | - MST: Minimum Spanning Tree 99 | - SL: Split & List 100 | - SP: Shortest Path 101 | - SW: Sliding Window 102 | - UF: Union Find 103 | 104 | ## Official Solutions 105 | 106 | For some problems, an [official solutions](official_solutions) was released. You can find them in this repository as well. 107 | -------------------------------------------------------------------------------- /official_solutions/algocoon.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/official_solutions/algocoon.pdf -------------------------------------------------------------------------------- /official_solutions/buddy-selection.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/official_solutions/buddy-selection.pdf -------------------------------------------------------------------------------- /official_solutions/car_sharing.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/official_solutions/car_sharing.pdf -------------------------------------------------------------------------------- /official_solutions/even_matrices.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/official_solutions/even_matrices.pdf -------------------------------------------------------------------------------- /official_solutions/firsthit.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/official_solutions/firsthit.pdf -------------------------------------------------------------------------------- /official_solutions/germs.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/official_solutions/germs.pdf -------------------------------------------------------------------------------- /official_solutions/hiking-maps.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/official_solutions/hiking-maps.pdf -------------------------------------------------------------------------------- /official_solutions/inball.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/official_solutions/inball.pdf -------------------------------------------------------------------------------- /official_solutions/moving_books.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/official_solutions/moving_books.pdf -------------------------------------------------------------------------------- /official_solutions/olympicgames.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/official_solutions/olympicgames.pdf -------------------------------------------------------------------------------- /official_solutions/russia.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/official_solutions/russia.pdf -------------------------------------------------------------------------------- /official_solutions/secret_service.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/official_solutions/secret_service.pdf -------------------------------------------------------------------------------- /official_solutions/the_great_game.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/official_solutions/the_great_game.pdf -------------------------------------------------------------------------------- /src/algocoon.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | typedef boost::adjacency_list_traits traits; 6 | typedef boost::adjacency_list>>> 10 | graph; 11 | 12 | typedef traits::vertex_descriptor vertex_desc; 13 | typedef traits::edge_descriptor edge_desc; 14 | 15 | class edge_adder 16 | { 17 | graph &G; 18 | 19 | public: 20 | explicit edge_adder(graph &G) : G(G) {} 21 | 22 | void add_edge(int from, int to, long capacity) 23 | { 24 | auto c_map = boost::get(boost::edge_capacity, G); 25 | auto r_map = boost::get(boost::edge_reverse, G); 26 | const auto e = boost::add_edge(from, to, G).first; 27 | const auto rev_e = boost::add_edge(to, from, G).first; 28 | c_map[e] = capacity; 29 | c_map[rev_e] = 0; // reverse edge has no capacity! 30 | r_map[e] = rev_e; 31 | r_map[rev_e] = e; 32 | } 33 | }; 34 | 35 | using namespace std; 36 | 37 | void solve() 38 | { 39 | int n, m; 40 | cin >> n >> m; 41 | 42 | graph G(n); 43 | edge_adder adder(G); 44 | 45 | int u, v, c; 46 | for (int i = 0; i < m; ++i) { 47 | cin >> u >> v >> c; 48 | adder.add_edge(u, v, c); 49 | } 50 | 51 | long minCut = numeric_limits::max(); 52 | 53 | int source = 0; 54 | for (int target = 1; target < n; ++target) { 55 | long maxFlow = boost::push_relabel_max_flow(G, source, target); 56 | minCut = min(minCut, maxFlow); 57 | maxFlow = boost::push_relabel_max_flow(G, target, source); 58 | minCut = min(minCut, maxFlow); 59 | } 60 | cout << minCut << endl; 61 | } 62 | 63 | int main() 64 | { 65 | ios_base::sync_with_stdio(false); 66 | int t; 67 | cin >> t; 68 | for (int i = 0; i < t; ++i) 69 | { 70 | solve(); 71 | } 72 | return 0; 73 | } 74 | -------------------------------------------------------------------------------- /src/ant_challenge.cpp: -------------------------------------------------------------------------------- 1 | // STL includes 2 | #include 3 | #include 4 | 5 | // BGL includes 6 | #include 7 | #include 8 | #include 9 | 10 | typedef boost::adjacency_list > weighted_graph; 12 | typedef boost::property_map::type weight_map; 13 | typedef boost::graph_traits::edge_descriptor edge_desc; 14 | typedef boost::graph_traits::vertex_descriptor vertex_desc; 15 | 16 | using namespace std; 17 | 18 | int dijkstra_dist(const weighted_graph &G, int s, int t) { 19 | int n = boost::num_vertices(G); 20 | std::vector dist_map(n); 21 | 22 | boost::dijkstra_shortest_paths(G, s, 23 | boost::distance_map(boost::make_iterator_property_map( 24 | dist_map.begin(), boost::get(boost::vertex_index, G)))); 25 | 26 | return dist_map[t]; 27 | } 28 | 29 | void solve() 30 | { 31 | int n; cin >> n; 32 | int m; cin >> m; 33 | int s; cin >> s; 34 | int a; cin >> a; 35 | int b; cin >> b; 36 | 37 | 38 | vector graphs(s, weighted_graph(n)); 39 | vector weights(s); 40 | for (int i = 0; i < s; ++i) { 41 | weights[i] = boost::get(boost::edge_weight, graphs[i]); 42 | } 43 | 44 | int u, v, w; 45 | for (int i = 0; i < m; ++i) { 46 | cin >> u; 47 | cin >> v; 48 | for (int j = 0; j < s; ++j) { 49 | cin >> w; 50 | boost::add_edge(u, v, w, graphs[j]); 51 | } 52 | } 53 | 54 | int h; 55 | for (int i = 0; i < s; ++i) { 56 | cin >> h; 57 | } 58 | 59 | weighted_graph G(n); 60 | 61 | for (int i = 0; i < s; ++i) { 62 | vector mst; 63 | boost::kruskal_minimum_spanning_tree(graphs[i], back_inserter(mst)); 64 | for (auto e : mst) { 65 | int u = boost::source(e, graphs[i]); 66 | int v = boost::target(e, graphs[i]); 67 | boost::add_edge(u, v, weights[i][e], G); 68 | } 69 | } 70 | 71 | cout << dijkstra_dist(G, a, b) << endl; 72 | 73 | } 74 | 75 | int main() { 76 | int t; cin >> t; 77 | for (int i = 0; i < t; ++i) { 78 | solve(); 79 | } 80 | } -------------------------------------------------------------------------------- /src/antenna.cpp: -------------------------------------------------------------------------------- 1 | ///8 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | typedef CGAL::Exact_predicates_exact_constructions_kernel K; 11 | typedef CGAL::Exact_predicates_exact_constructions_kernel_with_sqrt KSqrt; 12 | typedef CGAL::Min_circle_2_traits_2 Traits; 13 | typedef CGAL::Min_circle_2_traits_2 TraitsSqrt; 14 | typedef CGAL::Min_circle_2 Min_circle; 15 | typedef CGAL::Min_circle_2 MinCircleSqrt; 16 | typedef K::Point_2 P; 17 | typedef KSqrt::Point_2 PSqrt; 18 | typedef KSqrt::FT FTSqrt; 19 | 20 | using namespace std; 21 | 22 | void print_sqrt(const FTSqrt &x2) 23 | { 24 | FTSqrt x = CGAL::sqrt(x2); 25 | long a = CGAL::to_double(x); 26 | while (a > 0 && a - 1 > x) a -= 1; 27 | while (a < x) a += 1; 28 | cout << setprecision(0) << fixed << a << endl; 29 | } 30 | 31 | void solve(int n) { 32 | vector

points; 33 | 34 | if (n == 1) { 35 | print_sqrt(0); 36 | return; 37 | } 38 | 39 | points.reserve(n); 40 | for (int i = 0; i < n; ++i) { 41 | long x, y; 42 | cin >> x; 43 | cin >> y; 44 | points.push_back(P(x, y)); 45 | } 46 | 47 | Min_circle minCircle(points.begin(), points.end(), true); 48 | 49 | vector pointsSqrt; 50 | for (auto p = minCircle.support_points_begin(); p != minCircle.support_points_end(); ++p) { 51 | long x = CGAL::to_double(p->x()); 52 | long y = CGAL::to_double(p->y()); 53 | pointsSqrt.push_back(PSqrt(x, y)); 54 | } 55 | MinCircleSqrt minCircleSqrt(pointsSqrt.begin(), pointsSqrt.end(), true); 56 | 57 | FTSqrt squared_radius = minCircleSqrt.circle().squared_radius(); 58 | print_sqrt(squared_radius); 59 | } 60 | 61 | int main() 62 | { 63 | ios_base::sync_with_stdio(false); 64 | int n; 65 | cin >> n; 66 | while (n > 0) { 67 | solve(n); 68 | cin >> n; 69 | } 70 | } -------------------------------------------------------------------------------- /src/asterix_the_gaul.cpp: -------------------------------------------------------------------------------- 1 | ///4 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace std; 11 | 12 | struct DistanceTime { 13 | long distance; 14 | long time; 15 | 16 | bool operator<(const DistanceTime& other) const { 17 | return time < other.time; 18 | } 19 | }; 20 | 21 | 22 | int n; // number of moves 23 | int m; // amount of magic potion 24 | long D; // distance to panoramix 25 | long T; // number of seconds it takes for the romans to reach the druid 26 | 27 | vector d; // traversed distance for each move 28 | vector t; // time required for each move 29 | vector s; // additional distance covered by every move after taking i gulps 30 | 31 | 32 | void computeDistanceTimePairs(int i, int end, int gulps, long distance, long remainingTime, vector &distanceTime) { 33 | if (remainingTime <= 0) { 34 | return; 35 | } 36 | 37 | if (i == end) { 38 | if (distance > 0) { 39 | distanceTime.push_back({distance, T - remainingTime}); 40 | } 41 | return; 42 | } 43 | 44 | // Use move 45 | computeDistanceTimePairs(i + 1, end, gulps, distance + d[i] + s[gulps], remainingTime - t[i], distanceTime); 46 | 47 | // Do not use move 48 | computeDistanceTimePairs(i + 1, end, gulps, distance, remainingTime, distanceTime); 49 | } 50 | 51 | bool isFeasible(int gulps) { 52 | 53 | // Split 54 | vector distanceTime1; 55 | vector distanceTime2; 56 | computeDistanceTimePairs(0, n / 2, gulps, 0, T, distanceTime1); 57 | computeDistanceTimePairs(n / 2, n, gulps, 0, T, distanceTime2); 58 | 59 | 60 | // Sort by time 61 | sort(distanceTime1.begin(), distanceTime1.end()); 62 | sort(distanceTime2.begin(), distanceTime2.end()); 63 | 64 | // Replace distance with max-distance for a given time 65 | for (int i = 1; i < distanceTime1.size(); ++i) { 66 | distanceTime1[i].distance = max(distanceTime1[i - 1].distance, distanceTime1[i].distance); 67 | } 68 | for (int i = 1; i < distanceTime2.size(); ++i) { 69 | distanceTime2[i].distance = max(distanceTime2[i - 1].distance, distanceTime2[i].distance); 70 | } 71 | 72 | // The maximal element of a single list is sufficient 73 | if (distanceTime1.back().distance >= D || distanceTime2.back().distance >= D) { 74 | return true; 75 | } 76 | 77 | // Merge both lists 78 | for (auto e1 : distanceTime1) { 79 | 80 | // Binary search in second list 81 | int a = 0; 82 | int b = distanceTime2.size() - 1; 83 | 84 | while (a != b) { 85 | int middle = (a + b + 1) / 2; 86 | 87 | auto e2 = distanceTime2[middle]; 88 | 89 | if (e1.time + e2.time < T) { 90 | a = middle; 91 | } else { 92 | b = middle - 1; 93 | } 94 | } 95 | auto e2 = distanceTime2[a]; 96 | 97 | // The combination is feasible 98 | if (e1.time + e2.time < T && e1.distance + e2.distance >= D) { 99 | return true; 100 | } 101 | } 102 | return false; 103 | } 104 | 105 | void solve() { 106 | 107 | cin >> n >> m >> D >> T; 108 | 109 | d = vector(n); 110 | t = vector(n); 111 | for (int i = 0; i < n; ++i) { 112 | cin >> d[i] >> t[i]; 113 | } 114 | s = vector(m + 2); 115 | for (int i = 1; i <= m; ++i) { 116 | cin >> s[i]; 117 | } 118 | 119 | // Binary search over number of gulps 120 | int a = 0; 121 | int b = m + 1; 122 | 123 | while (a != b) { 124 | int gulps = (a + b) / 2; 125 | 126 | if (isFeasible(gulps)) { 127 | b = gulps; 128 | } 129 | else { 130 | a = gulps + 1; 131 | } 132 | } 133 | 134 | if (a == m + 1) { 135 | cout << "Panoramix captured" << endl; 136 | } 137 | else { 138 | cout << a << endl; 139 | } 140 | } 141 | 142 | int main() { 143 | ios_base::sync_with_stdio(false); 144 | int t; cin >> t; 145 | for (int i = 0; i < t; ++i) { 146 | solve(); 147 | } 148 | } -------------------------------------------------------------------------------- /src/attack_of_the_clones.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | struct jedi { 10 | int a; 11 | int b; 12 | 13 | bool operator<(jedi& o) const { 14 | return b < o.b || (b == o.b && a < o.a); 15 | } 16 | }; 17 | 18 | // Get the maximum numbers of jedis, where a < b for every jedi 19 | int maxRegularJedis(int start, int end, vector jedis) { 20 | int count = 0; 21 | int lastEnd = start; 22 | for (jedi j : jedis) { 23 | if (j.b >= end) { 24 | break; 25 | } 26 | if (j.a > lastEnd) { 27 | ++count; 28 | lastEnd = j.b; 29 | } 30 | } 31 | return count; 32 | } 33 | 34 | void solve() { 35 | int n; cin >> n; 36 | int m; cin >> m; 37 | 38 | vector jedis(n); 39 | map jediDelta; 40 | int a, b; 41 | for (int i = 0; i < n; ++i) { 42 | cin >> a; 43 | cin >> b; 44 | jedis[i] = jedi({a, b}); 45 | jediDelta[a]++; 46 | jediDelta[(b + 1) % m]--; 47 | } 48 | 49 | // Find index with smallest number of jedis 50 | int start = -1; 51 | int overlaps = 0; 52 | int minOverlaps = numeric_limits::max(); 53 | for (auto d : jediDelta) { 54 | int index = d.first; 55 | int delta = d.second; 56 | overlaps += delta; 57 | if (overlaps < minOverlaps) { 58 | minOverlaps = overlaps; 59 | start = index; 60 | } 61 | } 62 | 63 | vector startJedis; 64 | vector regularJedis; 65 | for (jedi &j : jedis) { 66 | // Shift start to 0 67 | j.a = (j.a - start + m) % m; 68 | j.b = (j.b - start + m) % m; 69 | 70 | // Overlaps start => try this jedi as first jedi 71 | if (j.a > j.b) { 72 | startJedis.push_back(j); 73 | } 74 | // No overlap 75 | else { 76 | regularJedis.push_back(j); 77 | } 78 | } 79 | sort(regularJedis.begin(), regularJedis.end()); 80 | 81 | // Maximum without any of the start jedis 82 | int maxJedis = maxRegularJedis(-1, m, regularJedis); 83 | // Try every start jedi 84 | for (jedi j0 : startJedis) { 85 | int currentJedis = 1 + maxRegularJedis(j0.b, j0.a, regularJedis); 86 | maxJedis = max(maxJedis, currentJedis); 87 | } 88 | cout << maxJedis << endl; 89 | } 90 | 91 | int main() { 92 | ios_base::sync_with_stdio(false); 93 | int t; 94 | cin >> t; 95 | while(t--) { 96 | solve(); 97 | } 98 | return 0; 99 | } -------------------------------------------------------------------------------- /src/beach_bars.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | struct ij { 8 | int i; 9 | int j; 10 | }; 11 | 12 | void solve() { 13 | int n; cin >> n; 14 | vector positions; 15 | for (int i = 0; i < n; ++i) { 16 | int p; cin >> p; 17 | positions.push_back(p); 18 | } 19 | sort(positions.begin(), positions.end()); 20 | 21 | int i = 0; 22 | int j = 0; 23 | 24 | int maxParasols = -1; 25 | int smallestDistance = 200; 26 | vector bestPositions; 27 | 28 | while (i < n && j < n) { 29 | int width = positions[j] - positions[i]; 30 | int parasols = j - i + 1; 31 | 32 | // Compute score and compare 33 | int distance = (width + 1) / 2; 34 | int bestPosition = positions[i] + distance; 35 | 36 | if (parasols > maxParasols || (parasols == maxParasols && distance <= smallestDistance)) { 37 | 38 | // New best 39 | if (parasols > maxParasols || distance < smallestDistance) { 40 | bestPositions = vector(); 41 | smallestDistance = distance; 42 | } 43 | maxParasols = parasols; 44 | if (width % 2 == 1) { // Odd width => best position not unique 45 | bestPositions.push_back(bestPosition - 1); 46 | } 47 | bestPositions.push_back(bestPosition); 48 | 49 | 50 | } 51 | 52 | 53 | // Move window 54 | if (positions[j + 1] - positions[i] < 201 && j < n - 1) { 55 | ++j; 56 | } else { 57 | ++i; 58 | } 59 | } 60 | 61 | 62 | 63 | cout << maxParasols << " " << smallestDistance << endl; 64 | for (int p : bestPositions) { 65 | cout << p << " "; 66 | } 67 | cout << endl; 68 | } 69 | 70 | 71 | int main() { 72 | int t; cin >> t; 73 | for (int i = 0; i < t; ++i) { 74 | solve(); 75 | } 76 | } -------------------------------------------------------------------------------- /src/bistro.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | typedef CGAL::Exact_predicates_inexact_constructions_kernel K; 11 | typedef CGAL::Delaunay_triangulation_2 DT; 12 | 13 | 14 | using namespace std; 15 | 16 | void solve(int n) { 17 | vector existing(n); 18 | 19 | long x, y; 20 | for (int i = 0; i < n; ++i) { 21 | cin >> x >> y; 22 | existing[i] = K::Point_2(x, y); 23 | } 24 | 25 | DT dt; 26 | dt.insert(existing.begin(), existing.end()); 27 | 28 | int m; 29 | cin >> m; 30 | for (int j = 0; j < m; ++j) { 31 | cin >> x >> y; 32 | 33 | auto nearest = dt.nearest_vertex(K::Point_2(x, y)); 34 | 35 | long xi = long(nearest->point().x()); 36 | long yi = long(nearest->point().y()); 37 | long distance = (x - xi) * (x - xi) + (y - yi) * (y - yi); 38 | cout << distance << endl; 39 | } 40 | } 41 | 42 | 43 | int main() { 44 | ios_base::sync_with_stdio(false); 45 | int n; 46 | while (cin >> n && n > 0) { 47 | solve(n); 48 | } 49 | return 0; 50 | } -------------------------------------------------------------------------------- /src/boats.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | 9 | struct boat { 10 | int length; 11 | int ringPosition; 12 | 13 | bool operator<(boat &o) const { 14 | return ringPosition < o.ringPosition; 15 | } 16 | }; 17 | 18 | void solve() { 19 | int n; cin >> n; 20 | vector boats(n); 21 | int boatLength, ringPosition; 22 | for (int i = 0; i < n; ++i) { 23 | cin >> boatLength; 24 | cin >> ringPosition; 25 | boats[i] = boat({boatLength, ringPosition}); 26 | } 27 | sort(boats.begin(), boats.end()); 28 | 29 | int end = numeric_limits::min(); 30 | int count = 0; 31 | int lastIndex = -1; 32 | 33 | while (true) { 34 | 35 | // Initialization 36 | int i = lastIndex + 1; 37 | int firstEnd = numeric_limits::max(); 38 | int firstEndIdx = -1; 39 | 40 | while (i < n) { 41 | ringPosition = boats[i].ringPosition; 42 | boatLength = boats[i].length; 43 | int boatStart = max(end, ringPosition - boatLength); 44 | if (boatStart > ringPosition) { // Not a valid placement 45 | ++i; 46 | continue; 47 | } 48 | if (boatStart > firstEnd) { // Can not be optimal 49 | break; 50 | } 51 | int currentEnd = boatStart + boatLength; 52 | if (currentEnd < firstEnd) { // New optimum 53 | firstEnd = currentEnd; 54 | firstEndIdx = i; 55 | } 56 | ++i; 57 | } 58 | 59 | // No more boats possible 60 | if (firstEndIdx == -1) { 61 | break; 62 | } 63 | 64 | // Take boat and find next boat 65 | lastIndex = firstEndIdx; 66 | end = firstEnd; 67 | ++count; 68 | } 69 | cout << count << endl; 70 | 71 | } 72 | 73 | int main() { 74 | int t; cin >> t; 75 | for (int i = 0; i < t; ++i) { 76 | solve(); 77 | } 78 | } -------------------------------------------------------------------------------- /src/buddy_selection.cpp: -------------------------------------------------------------------------------- 1 | // STL includes 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | // BGL includes 8 | #include 9 | #include 10 | 11 | using namespace std; 12 | 13 | typedef boost::adjacency_list graph; 14 | typedef boost::graph_traits::vertex_descriptor vertex_desc; 15 | 16 | bool perfect_matching(const graph &G) { 17 | int n = boost::num_vertices(G); 18 | vector mate_map(n); // exterior property map 19 | 20 | boost::edmonds_maximum_cardinality_matching(G, 21 | boost::make_iterator_property_map(mate_map.begin(), boost::get(boost::vertex_index, G))); 22 | int matching_size = boost::matching_size(G, 23 | boost::make_iterator_property_map(mate_map.begin(), boost::get(boost::vertex_index, G))); 24 | 25 | return 2 * matching_size == n; 26 | } 27 | 28 | void solve() { 29 | 30 | int n; cin >> n; 31 | int c; cin >> c; 32 | unsigned int f; cin >> f; 33 | 34 | graph G(n); 35 | 36 | string x; 37 | vector> ch(n, set()); 38 | for (int i = 0; i < n; ++i) { 39 | for (int j = 0; j < c; ++j) { 40 | cin >> x; 41 | ch[i].insert(x); 42 | } 43 | } 44 | 45 | 46 | for (int i = 0; i < n; ++i) { 47 | for (int j = 0; j < i; ++j) { 48 | vector intersection; 49 | set_intersection(ch[i].begin(), ch[i].end(), ch[j].begin(), ch[j].end(), back_inserter(intersection)); 50 | if (intersection.size() > f) { 51 | boost::add_edge(i, j, G); 52 | } 53 | } 54 | } 55 | 56 | cout << (perfect_matching(G) ? "not optimal" : "optimal") << endl; 57 | } 58 | 59 | int main() 60 | { 61 | ios_base::sync_with_stdio(false); 62 | int t; cin >> t; 63 | for (int i = 0; i < t; ++i) { 64 | solve(); 65 | } 66 | return 0; 67 | } -------------------------------------------------------------------------------- /src/build_the_sum.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | void solve() { 5 | int n; cin >> n; 6 | int sum = 0; 7 | for (int i = 0; i < n; ++i) { 8 | int a; cin >> a; 9 | sum += a; 10 | } 11 | cout << sum << endl; 12 | } 13 | 14 | int main() { 15 | int t; cin >> t; 16 | for (int i = 0; i < t; ++i) { 17 | solve(); 18 | } 19 | } -------------------------------------------------------------------------------- /src/burning_coins.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int solve() { 6 | int n; std::cin >> n; 7 | std::vector v; 8 | int vi; 9 | std::vector> min; 10 | std::vector> max; 11 | for (int i = 0; i < n; ++i) { 12 | std::cin >> vi; 13 | v.push_back(vi); 14 | min.push_back(std::vector(n, -1)); 15 | max.push_back(std::vector(n, -1)); 16 | } 17 | 18 | for (int length = 0; length < n; ++length) { 19 | for (int i = 0; i < n - length; ++i) { 20 | int j = i + length; 21 | if (length == 0) { 22 | min[i][j] = v[i]; 23 | max[i][j] = v[i]; 24 | } else if (length == 1) { 25 | min[i][j] = std::min(v[i], v[j]); 26 | max[i][j] = std::max(v[i], v[j]); 27 | } else { 28 | min[i][j] = std::min(max[i + 1][j], max[i][j - 1]); 29 | max[i][j] = std::max(v[i] + min[i + 1][j], min[i][j - 1] + v[j]); 30 | } 31 | } 32 | } 33 | return max[0][n - 1]; 34 | } 35 | 36 | int main() { 37 | int t; std::cin >> t; 38 | for (int i = 0; i < t; ++i) { 39 | int solution = solve(); 40 | std::cout << solution << std::endl; 41 | } 42 | } -------------------------------------------------------------------------------- /src/carsharing.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 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 | 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 | // Strategy: 47 | // - Build a space-time graph, i.e. a vertex is described by a tuple (i, t) where i is the rental station and t is the time 48 | // - We add edges for every booking and for parking (stay at the same station until the next time step) 49 | // - Use Maxflow-Mincost to solve the problem 50 | void solve() { 51 | 52 | // Read input 53 | int n, m; 54 | cin >> n >> m; 55 | 56 | vector l(m); // initially available cars 57 | int sumCars = 0; // How many cars are there in total? 58 | for (int j = 0; j < m; ++j) { 59 | cin >> l[j]; 60 | sumCars += l[j]; 61 | } 62 | 63 | // Save the relevant timesteps for each station (a timestep is only relevant if a booking starts or ends at the given station) 64 | vector> timePoints(m); 65 | 66 | vector s(n); // source 67 | vector t(n); // target 68 | vector d(n); // departure time 69 | vector a(n); // arrival time 70 | vector p(n); // profit 71 | int tMax = 0; 72 | for (int i = 0; i < n; ++i) { 73 | 74 | // Read input 75 | cin >> s[i] >> t[i] >> d[i] >> a[i] >> p[i]; 76 | --s[i]; --t[i]; // convert 1-based to 0-based indices 77 | 78 | // Save relevant time points 79 | timePoints[s[i]].insert(d[i]); 80 | timePoints[t[i]].insert(a[i]); 81 | tMax = max(tMax, a[i]); 82 | } 83 | 84 | // Time 0 and tMax are relevant for connecting to source and target 85 | for (int j = 0; j < m; ++j) { 86 | timePoints[j].insert(0); 87 | timePoints[j].insert(tMax); 88 | } 89 | 90 | // For every station: 91 | // - Assign a vertex id to every time point 92 | // - Sort relevant time points 93 | vector> timeToVertex(m); 94 | vector> sortedTimePoints(m); 95 | int id = 0; 96 | for (int j = 0; j < m; ++j) { 97 | for (int t : timePoints[j]) { 98 | timeToVertex[j][t] = id++; 99 | sortedTimePoints[j].push_back(t); 100 | } 101 | sort(sortedTimePoints[j].begin(), sortedTimePoints[j].end()); 102 | } 103 | 104 | // Create graph 105 | int N = id; 106 | graph G(N); 107 | edge_adder adder(G); 108 | 109 | // Connect consecutive time points 110 | for (int j = 0; j < m; ++j) { 111 | for (int i = 0; i < sortedTimePoints[j].size() - 1; ++i) { 112 | int t0 = sortedTimePoints[j][i]; 113 | int t1 = sortedTimePoints[j][i + 1]; 114 | adder.add_edge(timeToVertex[j][t0], timeToVertex[j][t1], sumCars, 100 * (t1 - t0)); 115 | } 116 | } 117 | 118 | // Add edges for booking requests 119 | for (int i = 0; i < n; ++i) { 120 | adder.add_edge(timeToVertex[s[i]][d[i]], timeToVertex[t[i]][a[i]], 1, 100 * (a[i] - d[i]) - p[i]); 121 | } 122 | 123 | // Connect source and sink 124 | int source = boost::add_vertex(G); 125 | int target = boost::add_vertex(G); 126 | for (int j = 0; j < m; ++j) { 127 | adder.add_edge(source, timeToVertex[j][0], l[j], 0); 128 | adder.add_edge(timeToVertex[j][tMax], target, sumCars, 0); 129 | } 130 | 131 | boost::successive_shortest_path_nonnegative_weights(G, source, target); 132 | int cost = boost::find_flow_cost(G); 133 | cost = 100 * sumCars * tMax - cost; 134 | 135 | cout << cost << endl; 136 | } 137 | 138 | int main() { 139 | ios_base::sync_with_stdio(false); 140 | int t; 141 | cin >> t; 142 | while (t--) { 143 | solve(); 144 | } 145 | return 0; 146 | } -------------------------------------------------------------------------------- /src/casino.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | // Graph Type with nested interior edge properties for Cost Flow Algorithms 9 | typedef boost::adjacency_list_traits traits; 10 | typedef boost::adjacency_list>>>> 15 | graph; // new! weightmap corresponds to costs 16 | typedef boost::graph_traits::edge_descriptor edge_desc; 17 | typedef boost::graph_traits::out_edge_iterator out_edge_it; // Iterator 18 | 19 | // Custom edge adder class 20 | class edge_adder 21 | { 22 | graph &G; 23 | 24 | public: 25 | explicit edge_adder(graph &G) : G(G) {} 26 | void add_edge(int from, int to, long capacity, long cost) 27 | { 28 | auto c_map = boost::get(boost::edge_capacity, G); 29 | auto r_map = boost::get(boost::edge_reverse, G); 30 | auto w_map = boost::get(boost::edge_weight, G); // new! 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; // reverse edge has no capacity! 35 | r_map[e] = rev_e; 36 | r_map[rev_e] = e; 37 | w_map[e] = cost; // new assign cost 38 | w_map[rev_e] = -cost; // new negative cost 39 | } 40 | }; 41 | 42 | using namespace std; 43 | 44 | 45 | // Idea: 46 | // Train has l seats. 47 | // Each seat can either be occupied by an agent or a regular passenger. 48 | // An agent on a mission brings reward q, a regular passenger 0. 49 | // l people board the train 50 | // At a given stop: 51 | // - either start mission to target-stop with value q 52 | // - or travel to next stop without reward 53 | void solve() 54 | { 55 | int stops, missions, maxAgents; 56 | cin >> stops >> missions >> maxAgents; 57 | 58 | int maxValue = 128; // 2^7 59 | 60 | graph G(stops); 61 | edge_adder adder(G); 62 | auto c_map = boost::get(boost::edge_capacity, G); 63 | auto r_map = boost::get(boost::edge_reverse, G); 64 | auto rc_map = boost::get(boost::edge_residual_capacity, G); 65 | 66 | auto source = boost::add_vertex(G); 67 | auto target = boost::add_vertex(G); 68 | 69 | adder.add_edge(source, 0, maxAgents, 0); 70 | adder.add_edge(stops - 1, target, maxAgents, 0); 71 | 72 | for (int stop = 0; stop < stops - 1; ++stop) { 73 | adder.add_edge(stop, stop + 1, maxAgents, maxValue); 74 | } 75 | 76 | int u, v, q; 77 | for (int mission = 0; mission < missions; ++mission) { 78 | cin >> u >> v >> q; 79 | adder.add_edge(u, v, 1, maxValue * (v - u) - q); 80 | } 81 | 82 | boost::successive_shortest_path_nonnegative_weights(G, source, target); 83 | auto cost = boost::find_flow_cost(G); 84 | cost = maxAgents * maxValue * (stops - 1) - cost; 85 | cout << cost << endl; 86 | } 87 | 88 | int main() 89 | { 90 | int t; cin >> t; 91 | for (int i = 0; i < t; ++i) { 92 | solve(); 93 | } 94 | return 0; 95 | } 96 | -------------------------------------------------------------------------------- /src/chariot_race.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | 9 | // Cost of the subtree 10 | struct cost { 11 | // Root (of subtree) selected 12 | int selected; 13 | // Parent is selected, i.e. root is already covered 14 | int covered; 15 | // Parent is not selected, at least one child needs to be selected to cover root 16 | int notCovered; 17 | }; 18 | 19 | 20 | cost calculateCost(int u, vector &costs, vector> &neighbors) { 21 | 22 | // Leaf node: just cost of leaf if selected, if not covered, we must select leaf 23 | if (neighbors[u].size() == 0) { 24 | return {costs[u], 0, costs[u]}; 25 | } 26 | 27 | cost current = {costs[u], 0, 0}; 28 | int bestDiff = numeric_limits::max(); 29 | for (auto v : neighbors[u]) { 30 | auto costV = calculateCost(v, costs, neighbors); 31 | current.selected += costV.covered; 32 | current.covered += costV.notCovered; 33 | bestDiff = min(bestDiff, costV.selected - costV.notCovered); 34 | } 35 | 36 | // Best we can do when we need to select one child 37 | current.notCovered = current.covered + bestDiff; 38 | 39 | // It can never be more expensive than selecting the vertex 40 | current.covered = min(current.selected, current.covered); 41 | current.notCovered = min(current.selected, current.notCovered); 42 | 43 | return current; 44 | } 45 | 46 | 47 | // Important observation: 48 | // A connected graph with n-1 edges is a tree 49 | // The root of the tree will always be vertex 0 50 | void solve() { 51 | int n; cin >> n; 52 | 53 | vector> neighbors(n, vector()); 54 | int u, v; 55 | for (int i = 0; i < n - 1; ++i) { 56 | cin >> u >> v; 57 | neighbors[u].push_back(v); 58 | } 59 | vector costs(n); 60 | for (int i = 0; i < n; ++i) { 61 | cin >> costs[i]; 62 | } 63 | 64 | cost total = calculateCost(0, costs, neighbors); 65 | cout << total.notCovered << endl; 66 | } 67 | 68 | 69 | int main() { 70 | ios_base::sync_with_stdio(false); 71 | int t; cin >> t; 72 | for (int i = 0; i < t; ++i) { 73 | solve(); 74 | } 75 | return 0; 76 | } 77 | -------------------------------------------------------------------------------- /src/clues.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | typedef CGAL::Exact_predicates_inexact_constructions_kernel K; 18 | typedef int Info; 19 | typedef CGAL::Triangulation_vertex_base_with_info_2 Vb; 20 | typedef CGAL::Triangulation_face_base_2 Fb; 21 | typedef CGAL::Triangulation_data_structure_2 Tds; 22 | typedef CGAL::Delaunay_triangulation_2 DT; 23 | typedef Tds::Vertex_handle Vh; 24 | typedef std::pair IPoint; 25 | 26 | typedef boost::adjacency_list graph; 27 | typedef boost::graph_traits::vertex_descriptor vertex_desc; 28 | typedef boost::graph_traits::edge_iterator edge_it; 29 | 30 | typedef std::vector partition_t; 31 | typedef typename boost::property_map ::type index_map_t; 32 | typedef boost::iterator_property_map partition_map_t; 33 | 34 | using namespace std; 35 | 36 | 37 | // Use the Delaunay Triangulation to find and add all vertices, 38 | // that are closer than r 39 | void addAllInRange(Vh u, DT& dt, graph& G, K::FT& r2) { 40 | set visited; 41 | 42 | vector q; 43 | q.push_back(u); 44 | visited.insert(u); 45 | 46 | while (!q.empty()) { 47 | 48 | auto v = q[q.size() - 1]; 49 | q.pop_back(); 50 | 51 | if (u != v) { 52 | boost::add_edge(u->info(), v->info(), G); 53 | } 54 | 55 | auto neighbor = v->incident_vertices(); 56 | do { 57 | if (!dt.is_infinite(neighbor) && visited.find(neighbor) == visited.end() && CGAL::squared_distance(u->point(), neighbor->point()) <= r2) { 58 | visited.insert(neighbor); 59 | q.push_back(neighbor); 60 | } 61 | } while(++neighbor != v->incident_vertices()); 62 | } 63 | } 64 | 65 | void solve() 66 | { 67 | int n, m; 68 | K::FT r; 69 | cin >> n >> m >> r; 70 | 71 | auto r2 = r * r; 72 | 73 | vector pts(n); 74 | long x, y; 75 | for (int i = 0; i < n; ++i) 76 | { 77 | cin >> x >> y; 78 | pts[i] = {K::Point_2(x, y), i}; 79 | } 80 | 81 | DT dt; 82 | dt.insert(pts.begin(), pts.end()); 83 | 84 | 85 | // Construct graph of potentially conflicting stations 86 | graph G(n); 87 | for (auto u = dt.finite_vertices_begin(); u != dt.finite_vertices_end(); ++u) { 88 | addAllInRange(u, dt, G, r2); 89 | } 90 | 91 | 92 | // Use BGL check for interference (no interference iff bipartit) 93 | auto is_bipartite = boost::is_bipartite(G); 94 | 95 | // Connected components: 96 | std::vector component_map(n); 97 | boost::connected_components(G, boost::make_iterator_property_map(component_map.begin(), boost::get(boost::vertex_index, G))); 98 | 99 | int x1, x2, y1, y2; 100 | for (int j = 0; j < m; ++j) 101 | { 102 | cin >> x1 >> y1 >> x2 >> y2; 103 | 104 | if (!is_bipartite) { 105 | cout << "n"; 106 | continue; 107 | } 108 | 109 | auto p1 = K::Point_2(x1, y1); 110 | auto p2 = K::Point_2(x2, y2); 111 | 112 | if (CGAL::squared_distance(p1, p2) <= r2) { 113 | cout << "y"; 114 | continue; 115 | } 116 | 117 | auto v1 = dt.nearest_vertex(p1); 118 | auto v2 = dt.nearest_vertex(p2); 119 | 120 | if (CGAL::squared_distance(p1, v1->point()) > r2 || CGAL::squared_distance(p2, v2->point()) > r2 ) { 121 | cout << "n"; 122 | continue; 123 | } 124 | 125 | if (component_map[v1->info()] == component_map[v2->info()]) { 126 | cout << "y"; 127 | } 128 | else { 129 | cout << "n"; 130 | } 131 | } 132 | cout << endl; 133 | 134 | } 135 | 136 | int main() 137 | { 138 | ios_base::sync_with_stdio(false); 139 | int t; 140 | cin >> t; 141 | for (int i = 0; i < t; ++i) 142 | { 143 | solve(); 144 | } 145 | return 0; 146 | } -------------------------------------------------------------------------------- /src/deck_of_cards.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | void solve() { 7 | int n; cin >> n; 8 | int k; cin >> k; 9 | int vi; 10 | vector v; 11 | for (int i = 0; i < n; ++i) { 12 | cin >> vi; 13 | v.push_back(vi); 14 | } 15 | int i = 0, j = 0; 16 | int bestI = 0, bestJ = 0; 17 | int best = 1073741834; 18 | int currentSum = 0; 19 | int value; 20 | while (j < n) { 21 | 22 | currentSum += v[j]; 23 | value = abs(k - currentSum); 24 | 25 | while (i <= j) { 26 | if (abs(k - (currentSum - v[i])) < value) { 27 | currentSum -= v[i]; 28 | ++i; 29 | value = abs(k - currentSum); 30 | } 31 | else { 32 | break; 33 | } 34 | } 35 | 36 | if (value < best) { 37 | best = value; 38 | bestI = i; 39 | bestJ = j; 40 | } 41 | ++j; 42 | } 43 | cout << bestI << " " << bestJ << endl; 44 | } 45 | 46 | int main() { 47 | int t; cin >> t; 48 | for (int i = 0; i < t; ++i) { 49 | solve(); 50 | } 51 | } -------------------------------------------------------------------------------- /src/defensive_line.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | void solve() { 8 | int n, m, k; 9 | cin >> n; 10 | cin >> m; 11 | cin >> k; 12 | 13 | vector v(n); 14 | for (int i = 0; i < n; ++i) { 15 | cin >> v[i]; 16 | } 17 | vector sum(n + 1); 18 | sum[0] = 0; 19 | for (int i = 0; i < n; ++i) { 20 | sum[i + 1] = v[i] + sum[i]; 21 | } 22 | 23 | // Sliding window to get a, b with sum = k 24 | 25 | int a = 0; 26 | int b = 0; 27 | vector startOfIntervall(n + 1, -1); 28 | 29 | while (a <= n && b <= n) { 30 | if (sum[b] - sum[a] == k) { 31 | startOfIntervall[b] = a; 32 | } 33 | 34 | // Sum would be to large if we were to move b, thus move a 35 | if (sum[b + 1] - sum[a] > k) { 36 | ++a; 37 | } 38 | else { 39 | ++b; 40 | } 41 | } 42 | 43 | vector> dp(m + 1, vector(n + 1, -1)); 44 | 45 | for (int attackers = 1; attackers <= m; ++attackers) { 46 | dp[attackers][0] = -1; 47 | for (int i = 1; i <= n; ++i) { 48 | int i0 = startOfIntervall[i]; 49 | if (attackers == 1) { 50 | int newValue = (i0 == -1) ? -1 : (i - i0); 51 | dp[attackers][i] = max(dp[attackers][i - 1], newValue); 52 | } 53 | else { 54 | int newValue = -1; 55 | if (i0 != -1 && dp[attackers - 1][i0] != -1) { 56 | newValue = i - i0; 57 | newValue += dp[attackers - 1][i0]; 58 | } 59 | dp[attackers][i] = max(dp[attackers][i - 1], newValue); 60 | } 61 | } 62 | } 63 | 64 | /* 65 | for (int row = 1; row <= m; ++row) { 66 | for (int col = 1; col <= n; ++col) { 67 | cout << dp[row][col] << " "; 68 | } 69 | cout << endl; 70 | } 71 | cout << endl; 72 | */ 73 | 74 | if (dp[m][n] == -1) { 75 | cout << "fail" << endl; 76 | } else { 77 | cout << dp[m][n] << endl; 78 | } 79 | } 80 | 81 | int main() { 82 | int t; cin >> t; 83 | for (int i = 0; i < t; ++i) { 84 | solve(); 85 | } 86 | } -------------------------------------------------------------------------------- /src/diet.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | typedef int IT; // input type 8 | typedef CGAL::Gmpz ET; // exact type for solver 9 | 10 | typedef CGAL::Quadratic_program Program; 11 | typedef CGAL::Quadratic_program_solution Solution; 12 | 13 | using namespace std; 14 | 15 | void solve(int n, int m) { 16 | vector a(n); 17 | vector b(n); 18 | for (int i = 0; i < n; ++i) { 19 | cin >> a[i]; 20 | cin >> b[i]; 21 | } 22 | vector p(m); 23 | vector> c(m, vector(n)); 24 | for (int j = 0; j < m; ++j) { 25 | cin >> p[j]; 26 | for (int i = 0; i < n; ++i) { 27 | cin >> c[j][i]; 28 | } 29 | } 30 | 31 | Program lp = Program(CGAL::SMALLER, true, 0, false, 0); 32 | 33 | for (int i = 0; i < n; ++i) { 34 | lp.set_b(i, b[i]); // xi <= b 35 | lp.set_b(i + n, -a[i]); // a <= xi <=> -xi <= -a 36 | 37 | for (int j = 0; j < m; ++j) { 38 | lp.set_a(j, i, c[j][i]); 39 | lp.set_a(j, i + n, -c[j][i]); 40 | } 41 | } 42 | 43 | for (int j = 0; j < m; ++j) { 44 | lp.set_c(j, p[j]); 45 | } 46 | 47 | Solution s = CGAL::solve_linear_program(lp, ET()); 48 | 49 | if (s.is_infeasible()) { 50 | cout << "No such diet." << endl; 51 | } else { 52 | cout << setprecision(0) << fixed << floor(CGAL::to_double(s.objective_value())) << endl; 53 | } 54 | } 55 | 56 | int main() { 57 | int n, m; 58 | while (cin >> n && n > 0) { 59 | cin >> m; 60 | solve(n, m); 61 | } 62 | return 0; 63 | } -------------------------------------------------------------------------------- /src/dominoes.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int solve() { 7 | int n; cin >> n; 8 | int max_index; cin >> max_index; 9 | for (int i = 1; i < n; ++i) { 10 | if (max_index <= i) { 11 | // Consume rest of input 12 | for (int j = i; j < n; ++j) { 13 | cin >> max_index; 14 | } 15 | return i; 16 | } 17 | int h; cin >> h; 18 | max_index = max(max_index, h + i); 19 | } 20 | return n; 21 | } 22 | 23 | int main() { 24 | int t; cin >> t; 25 | for (int i = 0; i < t; ++i) { 26 | int solution = solve(); 27 | cout << solution << endl; 28 | } 29 | } -------------------------------------------------------------------------------- /src/even_matrices.cpp: -------------------------------------------------------------------------------- 1 | // From the official solution 2 | #include 3 | #include 4 | 5 | typedef std::vector VI; 6 | typedef std::vector VVI; 7 | 8 | void testcase() { 9 | int n; 10 | std::cin >> n; 11 | 12 | // Input matrix 13 | VVI M = VVI(n + 1, VI(n + 1)); 14 | // pm[i][j] = sum of elements in the submatrix (1, 1, i, j) 15 | VVI pM = VVI(n + 1, VI(n + 1)); 16 | 17 | for (int i = 1; i <= n; ++i) 18 | for (int j = 1; j <= n; ++j) 19 | std::cin >> M[i][j]; 20 | 21 | 22 | for (int i = 0; i <= n; ++i) { 23 | pM[0][i] = 0; 24 | pM[i][0] = 0; 25 | } 26 | 27 | 28 | for (int i = 1; i <= n; ++i) 29 | for (int j = 1; j <= n; ++j) 30 | pM[i][j] = pM[i - 1][j] + pM[i][j - 1] - pM[i - 1][j - 1] + M[i][j]; 31 | 32 | 33 | int solution = 0; 34 | 35 | for (int i1 = 1; i1 <= n; ++i1) { 36 | for (int i2 = i1; i2 <= n; ++i2) { 37 | 38 | // We reduce the problem to one dimension. 39 | VI S(201); // We do Even Pairs on array S. 40 | VI pS(201); // pS contains partial sums of S. 41 | pS[0] = 0; 42 | 43 | for (int k = 1; k <= n; ++k) { 44 | S[k] = pM[i2][k] - pM[i2][k - 1] - pM[i1 - 1][k] + pM[i1 - 1][k - 1]; 45 | pS[k] = pS[k - 1] + S[k]; 46 | } 47 | 48 | // Do Even Pairs O(n) algorithm on array S. 49 | // even = number of partial sums of array that are even. 50 | // odd = number of partial sums of array that are odd. 51 | int even = 0, odd = 0; 52 | for (int j = 1; j <= n; ++j) { 53 | if (pS[j] % 2 == 0) ++even; 54 | else ++odd; 55 | } 56 | 57 | solution += even * (even - 1) / 2; 58 | solution += odd * (odd - 1) / 2; 59 | solution += even; 60 | } 61 | } 62 | 63 | std::cout << solution << std::endl; 64 | } 65 | 66 | int main() { 67 | std::ios_base::sync_with_stdio(false); 68 | int t; 69 | std::cin >> t; 70 | for (int i = 0; i < t; ++i) { 71 | testcase(); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/even_pairs.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int solve() { 5 | int n; cin >> n; 6 | int sum = 0; 7 | int even = 0; 8 | for (int i = 0; i < n; ++i) { 9 | int x; cin >> x; 10 | sum += x; 11 | if (sum % 2 == 0) { 12 | ++even; 13 | } 14 | } 15 | int odd = n - even; 16 | return even * (even - 1) / 2 + odd * (odd - 1) / 2 + even; 17 | } 18 | 19 | int main() { 20 | int t; cin >> t; 21 | for (int i = 0; i < t; ++i) { 22 | int solution = solve(); 23 | cout << solution << endl; 24 | } 25 | } -------------------------------------------------------------------------------- /src/evolution.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | struct query { 9 | int id; 10 | int b; 11 | }; 12 | 13 | vector age; 14 | vector> children; 15 | vector> queries; 16 | vector answer; 17 | vector path; 18 | 19 | // Binary search over the current path to find largest element that is at most maxAge old 20 | int search(int maxAge) { 21 | int a = 0; 22 | int b = path.size() - 1; 23 | while (a != b) { 24 | int m = (a + b) / 2; 25 | if (age[path[m]] <= maxAge) { 26 | b = m; 27 | } else { 28 | a = m + 1; 29 | } 30 | } 31 | return path[a]; 32 | } 33 | 34 | // Use DFS to compute the path for the current vertex 35 | // Answer all queries for the current vertex by calling the search function 36 | void dfs(int u) { 37 | path.push_back(u); 38 | 39 | // Compute answers for queries at u 40 | for (query q : queries[u]) { 41 | answer[q.id] = search(q.b); 42 | } 43 | 44 | // Recursion 45 | for (int v : children[u]) { 46 | dfs(v); 47 | } 48 | 49 | path.pop_back(); 50 | } 51 | 52 | // Strategy: Use binary search to answer queries 53 | void solve() { 54 | int n, q; 55 | cin >> n >> q; 56 | 57 | // We will be working with integer indices 58 | map id; // From name to id 59 | vector name(n); // From id to name 60 | 61 | // Read vertices 62 | age = vector(n); 63 | for (int i = 0; i < n; ++i) { 64 | cin >> name[i]; 65 | cin >> age[i]; 66 | id[name[i]] = i; 67 | } 68 | 69 | // Read edges 70 | string parent, child; 71 | children = vector>(n); 72 | for (int i = 0; i < n - 1; ++i) { 73 | cin >> child >> parent; 74 | children[id[parent]].push_back(id[child]); 75 | } 76 | 77 | // Read queries 78 | string queryName; 79 | int maxAge; 80 | queries = vector>(n); 81 | 82 | for (int queryId = 0; queryId < q; ++queryId) { 83 | cin >> queryName >> maxAge; 84 | queries[id[queryName]].push_back({queryId, maxAge}); 85 | } 86 | 87 | // Call dfs, the dfs actually solves the problem 88 | answer = vector(n); 89 | path = vector(); 90 | dfs(id["luca"]); 91 | 92 | // Output answers 93 | for (int j = 0; j < q; ++j) { 94 | cout << name[answer[j]] << " "; 95 | } 96 | cout << endl; 97 | } 98 | 99 | int main() { 100 | ios_base::sync_with_stdio(false); 101 | int t; cin >> t; 102 | while (t--) { 103 | solve(); 104 | } 105 | return 0; 106 | } -------------------------------------------------------------------------------- /src/first_hit.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | typedef CGAL::Exact_predicates_exact_constructions_kernel K; 5 | typedef std::result_of::type IT; 6 | typedef K::Point_2 P; 7 | typedef K::Segment_2 S; 8 | typedef K::Ray_2 R; 9 | typedef K::FT FT; 10 | 11 | using namespace std; 12 | 13 | double floor_to_double(const K::FT& x) 14 | { 15 | double a = std::floor(CGAL::to_double(x)); 16 | while (a > x) a -= 1; 17 | while (a+1 <= x) a += 1; 18 | return a; 19 | } 20 | 21 | void print(const P &p) { 22 | cout << setprecision(0) << fixed << floor_to_double(p.x()) << " " << floor_to_double(p.y()) << endl; 23 | } 24 | 25 | P getIntersectionPoint(IT &intersection, P &xy) { 26 | if (const P* intersectionPoint = boost::get

(&*intersection)) { 27 | return *intersectionPoint; 28 | } 29 | 30 | const S* intersectionSegment = boost::get(&*intersection); 31 | FT sourceDist = CGAL::squared_distance(xy, intersectionSegment->source()); 32 | FT targetDist = CGAL::squared_distance(xy, intersectionSegment->target()); 33 | 34 | if (sourceDist < targetDist) { 35 | return intersectionSegment->source(); 36 | } 37 | return intersectionSegment->target(); 38 | } 39 | 40 | void solve(int n) { 41 | long x, y, a, b; 42 | cin >> x >> y >> a >> b; 43 | P xy = P(x, y); 44 | R ray = R(P(x, y), P(a, b)); 45 | FT minDist; 46 | bool hit = false; 47 | P intersection; 48 | 49 | vector segments(n); 50 | for (int i = 0; i < n; ++i) { 51 | long r, s, t, u; 52 | cin >> r >> s >> t >> u; 53 | segments[i] = S(P(r, s), P(t, u)); 54 | } 55 | 56 | random_shuffle(segments.begin(), segments.end()); 57 | 58 | int i; 59 | for (i = 0; i < n; ++i) { 60 | 61 | S segment = segments[i]; 62 | 63 | if (CGAL::do_intersect(ray, segment)) { 64 | auto rayIntersection = CGAL::intersection(ray, segment); 65 | intersection = getIntersectionPoint(rayIntersection, xy); 66 | hit = true; 67 | break; 68 | } 69 | } 70 | 71 | if (!hit) { 72 | cout << "no" << endl; 73 | return; 74 | } 75 | 76 | // Continue search 77 | S raySegment = S(xy, intersection); 78 | for (; i < n; ++i) { 79 | S segment = segments[i]; 80 | if (CGAL::do_intersect(raySegment, segment)) { 81 | auto rayIntersection = CGAL::intersection(ray, segment); 82 | intersection = getIntersectionPoint(rayIntersection, xy); 83 | raySegment = S(xy, intersection); 84 | } 85 | } 86 | 87 | print(intersection); 88 | } 89 | 90 | int main() { 91 | ios_base::sync_with_stdio(false); 92 | int n; 93 | cin >> n; 94 | while (n > 0) { 95 | solve(n); 96 | cin >> n; 97 | } 98 | return 0; 99 | } -------------------------------------------------------------------------------- /src/first_steps.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // BGL includes 5 | #include 6 | #include 7 | #include 8 | 9 | typedef boost::adjacency_list> weighted_graph; 10 | typedef boost::property_map::type weight_map; 11 | typedef boost::graph_traits::edge_descriptor edge_desc; 12 | typedef boost::graph_traits::vertex_descriptor vertex_desc; 13 | 14 | 15 | using namespace std; 16 | 17 | int dijkstra_dist(const weighted_graph &G, int s) { 18 | int n = boost::num_vertices(G); 19 | std::vector dist_map(n); 20 | 21 | boost::dijkstra_shortest_paths(G, s, 22 | boost::distance_map(boost::make_iterator_property_map( 23 | dist_map.begin(), boost::get(boost::vertex_index, G)))); 24 | 25 | int value = 0; 26 | for (int i = 0; i < n; ++i) { 27 | if (dist_map[i] != 2147483647) 28 | value = max(value, dist_map[i]); 29 | } 30 | 31 | return value; 32 | } 33 | 34 | void solve() { 35 | int n; cin >> n; 36 | int m; cin >> m; 37 | 38 | weighted_graph G(4); 39 | weight_map weights = boost::get(boost::edge_weight, G); 40 | 41 | int u, v, w; 42 | for (int i = 0; i < m; ++i) { 43 | cin >> u; 44 | cin >> v; 45 | cin >> w; 46 | boost::add_edge(u, v, w, G); 47 | } 48 | 49 | vector mst; // vector to store MST edges (not a property map!) 50 | 51 | boost::kruskal_minimum_spanning_tree(G, back_inserter(mst)); 52 | 53 | int weight = 0; 54 | for (vector::iterator it = mst.begin(); it != mst.end(); ++it) { 55 | weight += boost::get(boost::edge_weight_t(), G, *it); 56 | } 57 | 58 | cout << weight << " " << dijkstra_dist(G, 0) << endl; 59 | } 60 | 61 | int main() { 62 | int t; cin >> t; 63 | for (int i = 0; i < t; ++i) { 64 | solve(); 65 | } 66 | } -------------------------------------------------------------------------------- /src/fleetrace.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | // Graph Type with nested interior edge properties for Cost Flow Algorithms 9 | typedef boost::adjacency_list_traits traits; 10 | typedef boost::adjacency_list>>>> 15 | graph; // new! weightmap corresponds to costs 16 | typedef boost::graph_traits::edge_descriptor edge_desc; 17 | typedef boost::graph_traits::out_edge_iterator out_edge_it; // Iterator 18 | 19 | using namespace std; 20 | 21 | // Custom edge adder class 22 | class edge_adder 23 | { 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 | { 30 | auto c_map = boost::get(boost::edge_capacity, G); 31 | auto r_map = boost::get(boost::edge_reverse, G); 32 | auto w_map = boost::get(boost::edge_weight, G); // new! 33 | const edge_desc e = boost::add_edge(from, to, G).first; 34 | const edge_desc rev_e = boost::add_edge(to, from, G).first; 35 | c_map[e] = capacity; 36 | c_map[rev_e] = 0; // reverse edge has no capacity! 37 | r_map[e] = rev_e; 38 | r_map[rev_e] = e; 39 | w_map[e] = cost; // new assign cost 40 | w_map[rev_e] = -cost; // new negative cost 41 | } 42 | }; 43 | 44 | 45 | 46 | void solve() { 47 | int b, s, p; 48 | cin >> b >> s >> p; 49 | 50 | graph G(b + s); 51 | edge_adder adder(G); 52 | 53 | auto source = boost::add_vertex(G); 54 | auto target = boost::add_vertex(G); 55 | 56 | int maxValue = 50; 57 | 58 | for (int i = 0; i < b; ++i) { 59 | adder.add_edge(source, i, 1, 0); 60 | if (b <= s) { 61 | adder.add_edge(i, target, 1, maxValue); 62 | } 63 | } 64 | for (int j = 0; j < s; ++j) { 65 | adder.add_edge(b + j, target, 1, 0); 66 | if (b > s) { 67 | adder.add_edge(source, b + j, 1, maxValue); 68 | } 69 | } 70 | int bi, si, ci; 71 | for (int i = 0; i < p; ++i) { 72 | cin >> bi >> si >> ci; 73 | adder.add_edge(bi, b + si, 1, maxValue - ci); 74 | } 75 | 76 | boost::successive_shortest_path_nonnegative_weights(G, source, target); 77 | auto cost = boost::find_flow_cost(G); 78 | cost = min(b, s) * maxValue - cost; 79 | cout << cost << endl; 80 | } 81 | 82 | int main() { 83 | ios_base::sync_with_stdio(false); 84 | int t; cin >> t; 85 | for (int i = 0; i < t; ++i) { 86 | solve(); 87 | } 88 | return 0; 89 | } 90 | -------------------------------------------------------------------------------- /src/germs.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | typedef CGAL::Exact_predicates_inexact_constructions_kernel K; 13 | typedef CGAL::Exact_predicates_exact_constructions_kernel_with_sqrt K_sqrt; 14 | typedef CGAL::Delaunay_triangulation_2 DT; 15 | 16 | 17 | using namespace std; 18 | 19 | void solve(int n) { 20 | 21 | int l, b, r, t; 22 | cin >> l >> b >> r >> t; 23 | 24 | long x, y; 25 | vector pts(n); 26 | for (int i = 0; i < n; ++i) { 27 | cin >> x >> y; 28 | pts[i] = K::Point_2(x, y); 29 | } 30 | 31 | DT dt; 32 | dt.insert(pts.begin(), pts.end()); 33 | 34 | vector times; 35 | times.reserve(n); 36 | for (auto v = dt.vertices_begin(); v != dt.vertices_end(); ++v) { 37 | long xi = long(v->point().x()); 38 | long yi = long(v->point().y()); 39 | 40 | auto nearest = CGAL::nearest_neighbor(dt, v->handle()); 41 | 42 | double maxRadius = numeric_limits::max(); 43 | 44 | if (nearest != nullptr) { 45 | long xj = long(nearest->point().x()); 46 | long yj = long(nearest->point().y()); 47 | 48 | // Squared distance to neighbor 49 | long squaredDistance = (xi - xj) * (xi - xj) + (yi - yj) * (yi - yj); 50 | maxRadius = sqrt(squaredDistance) / 2; 51 | 52 | } 53 | // Distance to boarder 54 | long closestBorder = abs(xi - l); 55 | closestBorder = min(closestBorder, abs(xi - r)); 56 | closestBorder = min(closestBorder, abs(yi - t)); 57 | closestBorder = min(closestBorder, abs(yi - b)); 58 | 59 | maxRadius = min(maxRadius, (double) closestBorder); 60 | 61 | // r = t^2 + 0.5 62 | // t^2 = r - 0.5 63 | // t = sqrt(r - 0.5) 64 | auto time = 0.; 65 | if (maxRadius - 0.5 > 0){ 66 | time = sqrt(maxRadius - 0.5); 67 | } 68 | times.push_back(time); 69 | } 70 | 71 | sort(times.begin(), times.end()); 72 | 73 | cout << ceil(times[0]) << " " << ceil(times[n / 2]) << " " << ceil(times[n - 1]) << endl; 74 | 75 | } 76 | 77 | 78 | int main() { 79 | ios_base::sync_with_stdio(false); 80 | int n; 81 | while (cin >> n && n > 0) { 82 | solve(n); 83 | } 84 | return 0; 85 | } -------------------------------------------------------------------------------- /src/h1n1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | 16 | typedef CGAL::Exact_predicates_inexact_constructions_kernel K; 17 | typedef CGAL::Triangulation_vertex_base_2 Vb; 18 | typedef CGAL::Triangulation_face_base_with_info_2 Fb; 19 | typedef CGAL::Triangulation_data_structure_2 Tds; 20 | typedef CGAL::Delaunay_triangulation_2 Delaunay; 21 | 22 | typedef K::FT FT; 23 | 24 | using namespace std; 25 | 26 | struct Neighbor { 27 | int vertex; 28 | FT width; 29 | }; 30 | 31 | void solve(int numPoints) { 32 | 33 | long x, y; 34 | vector pts(numPoints); 35 | for (int i = 0; i < numPoints; ++i) { 36 | cin >> x >> y; 37 | pts[i] = {x, y}; 38 | } 39 | Delaunay dt; 40 | dt.insert(pts.begin(), pts.end()); 41 | 42 | int id = 1; 43 | for (auto f = dt.finite_faces_begin(); f != dt.finite_faces_end(); ++f) { 44 | f->info() = id++; 45 | } 46 | 47 | int n = id; 48 | vector> neighbors(n); 49 | for (auto f = dt.finite_faces_begin(); f != dt.finite_faces_end(); ++f) { 50 | int u = f->info(); 51 | 52 | for (int i = 0; i < 3; ++i) { 53 | auto f2 = f->neighbor(i); 54 | int v = dt.is_infinite(f2) ? 0 : f2->info(); 55 | auto p1 = f->vertex((i + 1) % 3)->point(); 56 | auto p2 = f->vertex((i + 2) % 3)->point(); 57 | FT width = CGAL::squared_distance(p1, p2); 58 | 59 | neighbors[u].push_back({v, width}); 60 | if (v == 0) { 61 | neighbors[v].push_back({u, width}); 62 | } 63 | } 64 | } 65 | 66 | FT maxValue = FT(numeric_limits::max()); 67 | 68 | vector width(n, -1); 69 | priority_queue> queue; 70 | queue.push({maxValue, 0}); 71 | 72 | while (!queue.empty()) { 73 | 74 | FT w = get<0>(queue.top()); 75 | int u = get<1>(queue.top()); 76 | queue.pop(); 77 | 78 | if (width[u] != -1) { 79 | continue; 80 | } 81 | 82 | width[u] = w; 83 | 84 | for (Neighbor n : neighbors[u]) { 85 | FT wn = CGAL::min(n.width, w); 86 | queue.push({wn, n.vertex}); 87 | } 88 | } 89 | 90 | int m; 91 | cin >> m; 92 | long d; 93 | for (int i = 0; i < m; ++i) { 94 | cin >> x >> y >> d; 95 | 96 | K::Point_2 p(x, y); 97 | 98 | if (CGAL::squared_distance(p, dt.nearest_vertex(p)->point()) < FT(d)) { 99 | cout << "n"; 100 | continue; 101 | } 102 | 103 | auto f = dt.locate(p); 104 | int v = dt.is_infinite(f) ? 0 : f->info(); 105 | 106 | if (width[v] >= FT(4) * FT(d)) { 107 | cout << "y"; 108 | } 109 | else { 110 | cout << "n"; 111 | } 112 | 113 | } 114 | cout << endl; 115 | } 116 | 117 | 118 | int main() { 119 | ios_base::sync_with_stdio(false); 120 | int n; 121 | cin >> n; 122 | while (n != 0) { 123 | solve(n); 124 | cin >> n; 125 | } 126 | return 0; 127 | } 128 | -------------------------------------------------------------------------------- /src/hand.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | typedef CGAL::Exact_predicates_inexact_constructions_kernel K; 13 | typedef int Index; 14 | typedef CGAL::Triangulation_vertex_base_with_info_2 Vb; 15 | typedef CGAL::Triangulation_face_base_2 Fb; 16 | typedef CGAL::Triangulation_data_structure_2 Tds; 17 | typedef CGAL::Delaunay_triangulation_2 DT; 18 | typedef std::pair IPoint; 19 | 20 | typedef boost::adjacency_list > weighted_graph; 22 | typedef boost::property_map::type weight_map; 23 | typedef boost::graph_traits::edge_descriptor edge_desc; 24 | typedef boost::graph_traits::vertex_descriptor vertex_desc; 25 | 26 | struct Edge { 27 | int u, v; 28 | long w; 29 | 30 | bool operator<(Edge e) const { 31 | return w < e.w; 32 | } 33 | }; 34 | 35 | typedef std::vector EdgeV; 36 | 37 | using namespace std; 38 | 39 | int maxFamilies(vector &componentsOfSize, int k) { 40 | int f = componentsOfSize[k]; 41 | if (k == 4) { 42 | if (componentsOfSize[3] <= componentsOfSize[1]) { 43 | f += componentsOfSize[3]; 44 | f += ((componentsOfSize[1] - componentsOfSize[3]) / 2 + componentsOfSize[2]) / 2; 45 | } 46 | else { 47 | f += componentsOfSize[1]; 48 | f += ((componentsOfSize[3] - componentsOfSize[1]) + componentsOfSize[2]) / 2; 49 | } 50 | } 51 | else if (k == 3) { 52 | if (componentsOfSize[2] <= componentsOfSize[1]) { 53 | f += componentsOfSize[2]; 54 | f += (componentsOfSize[1] - componentsOfSize[2]) / 3; 55 | } 56 | else { 57 | f += componentsOfSize[1]; 58 | f += (componentsOfSize[2] - componentsOfSize[1]) / 2; 59 | } 60 | } 61 | else if (k == 2) { 62 | f += componentsOfSize[1] / 2; 63 | } 64 | return f; 65 | } 66 | 67 | 68 | void solve() { 69 | int n, k, f0; 70 | long s0; 71 | cin >> n >> k >> f0 >> s0; 72 | 73 | vector pts(n); 74 | for (std::size_t i = 0; i < n; ++i) { 75 | int x, y; 76 | cin >> x >> y; 77 | pts[i] = {{x, y}, i}; 78 | } 79 | 80 | DT dt; 81 | dt.insert(pts.begin(), pts.end()); 82 | 83 | EdgeV edges; 84 | edges.reserve(3*n); 85 | for (auto e = dt.finite_edges_begin(); e != dt.finite_edges_end(); ++e) { 86 | int u = e->first->vertex((e->second+1)%3)->info(); 87 | int v = e->first->vertex((e->second+2)%3)->info(); 88 | if (u > v) swap(u, v); 89 | edges.push_back({u, v, long(dt.segment(e).squared_length())}); 90 | } 91 | 92 | std::sort(edges.begin(), edges.end()); 93 | 94 | boost::disjoint_sets_with_storage<> uf(n); 95 | Index n_components = n; 96 | vector sizeOfComponent(n, 1); 97 | vector componentsOfSize(k + 1, 0); 98 | long s = -1; 99 | int f = -1; 100 | componentsOfSize[1] = n; 101 | vector squaredDistances; 102 | for (auto e : edges) { 103 | Index c1 = uf.find_set(e.u); 104 | Index c2 = uf.find_set(e.v); 105 | if (c1 != c2) { 106 | 107 | int fMax = maxFamilies(componentsOfSize, k); 108 | 109 | if (fMax >= f0) { 110 | s = e.w; 111 | } 112 | if (e.w >= s0) { 113 | f = max(f, fMax); 114 | } 115 | 116 | squaredDistances.push_back(e.w); 117 | 118 | uf.link(c1, c2); 119 | int c = uf.find_set(c1); 120 | 121 | componentsOfSize[sizeOfComponent[c1]] -= 1; 122 | componentsOfSize[sizeOfComponent[c2]] -= 1; 123 | sizeOfComponent[c] = min(k, sizeOfComponent[c1] + sizeOfComponent[c2]); 124 | componentsOfSize[sizeOfComponent[c]] += 1; 125 | 126 | if (--n_components == 1) break; 127 | } 128 | } 129 | int fMax = maxFamilies(componentsOfSize, k); 130 | f = max(f, fMax); 131 | 132 | cout << s << " " << f << endl; 133 | } 134 | 135 | 136 | int main() 137 | { 138 | ios_base::sync_with_stdio(false); 139 | int t; cin >> t; 140 | while (t--) { 141 | solve(); 142 | } 143 | return 0; 144 | } 145 | -------------------------------------------------------------------------------- /src/hiking_maps.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | typedef CGAL::Exact_predicates_inexact_constructions_kernel K; 8 | typedef K::Point_2 P; 9 | typedef K::Line_2 L; 10 | typedef K::FT FT; 11 | typedef K::Triangle_2 T; 12 | 13 | 14 | using namespace std; 15 | 16 | struct wordIndex { 17 | int index; 18 | int word; 19 | 20 | bool operator<(const wordIndex &rhs) { 21 | return index < rhs.index; 22 | } 23 | }; 24 | 25 | 26 | P intersection(L& l1, L& l2) { 27 | auto i = CGAL::intersection(l1, l2); 28 | if (const P* p = boost::get

(&*i)) { 29 | return *p; 30 | } 31 | return P(-1, -1); 32 | } 33 | 34 | void solve() { 35 | int m, n; cin >> m; cin >> n; 36 | vector

pos; 37 | pos.reserve(m); 38 | int x, y; 39 | for (int i = 0; i < m; ++i) { 40 | cin >> x; cin >> y; 41 | pos.push_back(P(x, y)); 42 | } 43 | 44 | vector t; 45 | t.reserve(n); 46 | 47 | vector> p(m - 1, vector()); 48 | vector wordIndices; 49 | int lastWordIndex = 0; 50 | 51 | int px, py, qx, qy; 52 | L l1, l2, l3; 53 | P p1, q1, p2, q2, p3, q3; 54 | 55 | for (int i = 0; i < n; ++i) { 56 | cin >> px; cin >> py; cin >> qx; cin >> qy; 57 | p1 = P(px, py); 58 | q1 = P(qx, qy); 59 | cin >> px; cin >> py; cin >> qx; cin >> qy; 60 | p2 = P(px, py); 61 | q2 = P(qx, qy); 62 | cin >> px; cin >> py; cin >> qx; cin >> qy; 63 | p3 = P(px, py); 64 | q3 = P(qx, qy); 65 | 66 | l1 = L(p1, q1); 67 | l2 = L(p2, q2); 68 | l3 = L(p3, q3); 69 | 70 | if (l1.oriented_side(p2) < 0) { 71 | l1 = L(q1, p1); 72 | } 73 | if (l2.oriented_side(p1) < 0) { 74 | l2 = L(q2, p2); 75 | } 76 | if (l3.oriented_side(p2) < 0) { 77 | l3 = L(q3, p3); 78 | } 79 | 80 | vector pointInside(m); 81 | for (int j = 0; j < m; ++j) { 82 | auto side1 = l1.oriented_side(pos[j]); 83 | auto side2 = l2.oriented_side(pos[j]); 84 | auto side3 = l3.oriented_side(pos[j]); 85 | pointInside[j] = side1 >= 0 && side2 >= 0 && side3 >= 0; 86 | } 87 | 88 | for (int j = 0; j < m-1; ++j) { 89 | bool inside = pointInside[j] && pointInside[j + 1]; 90 | if (inside) { 91 | p[j].push_back(i); 92 | wordIndices.push_back(wordIndex{i, j}); 93 | } 94 | } 95 | 96 | } 97 | 98 | int w = wordIndices.size(); 99 | int minLength = numeric_limits::max(); 100 | 101 | for (int j = 0; j < m-1; ++j) { 102 | lastWordIndex = max(lastWordIndex, p[j][0]); 103 | } 104 | sort(wordIndices.begin(), wordIndices.end()); 105 | 106 | 107 | 108 | int i = 0; 109 | int j = 0; 110 | vector pi(m - 1, 0); 111 | 112 | // Move j to first position, where all words are covered 113 | while (j + 1 < w && wordIndices[j + 1].index <= lastWordIndex) { 114 | ++j; 115 | } 116 | 117 | while (i < w && j < w) { 118 | 119 | wordIndex a = wordIndices[i]; 120 | wordIndex b = wordIndices[j]; 121 | int length = b.index - a.index + 1; 122 | minLength = min(minLength, length); 123 | 124 | // Check if moving i is allowed 125 | bool moveI = true; 126 | int word = a.word; 127 | if (pi[word] + 1 >= p[word].size()) { 128 | // Already last occurrence of word 129 | break; 130 | } else { 131 | int nextWordIndex = p[word][pi[word] + 1]; 132 | moveI = a.index < nextWordIndex && nextWordIndex <= b.index; 133 | } 134 | 135 | if (moveI) { 136 | ++i; 137 | pi[word] += 1; 138 | } else { 139 | ++j; 140 | } 141 | } 142 | cout << minLength << endl; 143 | 144 | } 145 | 146 | int main() { 147 | ios_base::sync_with_stdio(false); 148 | int t; cin >> t; 149 | for (int i = 0; i < t; ++i) { 150 | solve(); 151 | } 152 | } -------------------------------------------------------------------------------- /src/hit.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | typedef CGAL::Exact_predicates_inexact_constructions_kernel K; 5 | typedef K::Point_2 P; 6 | typedef K::Segment_2 S; 7 | typedef K::Ray_2 R; 8 | 9 | using namespace std; 10 | 11 | int main() { 12 | ios_base::sync_with_stdio(false); 13 | 14 | int n; cin >> n; 15 | while (n > 0) { 16 | long x, y, a, b; 17 | cin >> x; cin >> y; cin >> a; cin >> b; 18 | R ray = R(P(x, y), P(a, b)); 19 | bool hit = false; 20 | for (int i = 0; i < n; ++i) { 21 | long r, s, t, u; 22 | cin >> r; cin >> s; cin >> t; cin >> u; 23 | 24 | // Already hit an obstacle, no need to test for intersection 25 | if (hit) { 26 | continue; 27 | } 28 | 29 | if (CGAL::do_intersect(ray, S(P(r, s), P(t, u)))) { 30 | hit = true; 31 | } 32 | } 33 | cout << (hit ? "yes" : "no") << endl; 34 | 35 | cin >> n; 36 | } 37 | } -------------------------------------------------------------------------------- /src/hongkong.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | typedef CGAL::Exact_predicates_exact_constructions_kernel K; 11 | typedef K::FT FT; 12 | struct FaceInfo { 13 | int id; 14 | FT r2; 15 | }; 16 | struct Neighbor { 17 | int vertex; 18 | FT width; 19 | }; 20 | 21 | typedef CGAL::Triangulation_vertex_base_with_info_2 Vb; 22 | typedef CGAL::Triangulation_face_base_with_info_2 Fb; 23 | typedef CGAL::Triangulation_data_structure_2 Tds; 24 | typedef CGAL::Delaunay_triangulation_2 DT; 25 | typedef std::pair IPoint; 26 | 27 | using namespace std; 28 | 29 | FT MAX_VALUE = FT(numeric_limits::max()) * FT(numeric_limits::max()); 30 | 31 | void solve() { 32 | int n, m; 33 | long r; 34 | 35 | cin >> n >> m >> r; 36 | 37 | // Construct Delaunay triangulation 38 | DT dt; 39 | long x, y; 40 | vector pts; 41 | pts.reserve(n); 42 | for (int i = 0; i < n; ++i) { 43 | cin >> x >> y; 44 | pts.emplace_back(K::Point_2(x, y), i); 45 | } 46 | dt.insert(pts.begin(), pts.end()); 47 | 48 | 49 | // Assign info to finite faces 50 | int id = 0; 51 | for (auto f = dt.finite_faces_begin(); f != dt.finite_faces_end(); ++f) { 52 | FT radius2 = CGAL::squared_distance(dt.dual(f), f->vertex(0)->point()); 53 | f->info() = {++id, radius2}; 54 | } 55 | 56 | // Create edges between adjacent faces 57 | vector> neighbors(id + 1); 58 | for (auto f = dt.finite_faces_begin(); f != dt.finite_faces_end(); ++f) { 59 | int u = f->info().id; 60 | 61 | // Connect neighbors 62 | for (int i = 0; i < 3; ++i) { 63 | auto neighbor = f->neighbor((i + 2) % 3); 64 | int v = dt.is_infinite(neighbor) ? 0 : neighbor->info().id; 65 | 66 | auto p1 = f->vertex(i)->point(); 67 | auto p2 = f->vertex((i + 1) % 3)->point(); 68 | FT width = CGAL::squared_distance(p1, p2); 69 | neighbors[u].push_back({v, width}); 70 | neighbors[v].push_back({u, width}); 71 | } 72 | 73 | // Connect to outside (balloon take-off) 74 | FT width = f->info().r2; 75 | neighbors[u].push_back({0, width}); 76 | neighbors[0].push_back({u, width}); 77 | } 78 | 79 | // Find widest path width a modified Dijkstra 80 | vector widestPath(id + 1, -1); 81 | 82 | priority_queue> q; 83 | q.push({MAX_VALUE, 0}); 84 | 85 | while (!q.empty()) { 86 | int u = get<1>(q.top()); 87 | FT maxWidth = get<0>(q.top()); 88 | q.pop(); 89 | 90 | if (widestPath[u] != -1) { 91 | continue; 92 | } 93 | widestPath[u] = maxWidth; 94 | 95 | for (auto &neighbor : neighbors[u]) { 96 | int v = neighbor.vertex; 97 | FT width = neighbor.width; 98 | if (widestPath[v] == -1) { 99 | FT neighborMaxWidth = min(widestPath[u], width); 100 | q.push({neighborMaxWidth, v}); 101 | } 102 | } 103 | } 104 | 105 | // Queries 106 | long s; 107 | for (int j = 0; j < m; ++j) { 108 | cin >> x >> y >> s; 109 | 110 | auto p = K::Point_2(x, y); 111 | auto nearest = dt.nearest_vertex(p); 112 | 113 | FT d = (FT(r) + FT(s)) * (FT(r) + FT(s)); 114 | 115 | // Balloon is too large for initial position 116 | if (CGAL::squared_distance(p, nearest->point()) < d) { 117 | cout << "n"; 118 | continue; 119 | } 120 | 121 | auto face = dt.locate(p); 122 | if (dt.is_infinite(face)) { 123 | cout << "y"; 124 | continue; 125 | } 126 | 127 | // Find widest path 128 | int v = face->info().id; 129 | if (widestPath[v] >= 4 * d) { 130 | cout << "y"; 131 | } 132 | else { 133 | cout << "n"; 134 | } 135 | } 136 | cout << endl; 137 | } 138 | 139 | int main() { 140 | ios_base::sync_with_stdio(false); 141 | int t; cin >> t; 142 | while (t--) { 143 | solve(); 144 | } 145 | return 0; 146 | } -------------------------------------------------------------------------------- /src/idefix.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | typedef CGAL::Exact_predicates_inexact_constructions_kernel K; 13 | typedef CGAL::Triangulation_vertex_base_with_info_2 Vb; 14 | typedef CGAL::Triangulation_face_base_2 Fb; 15 | typedef CGAL::Triangulation_data_structure_2 Tds; 16 | typedef CGAL::Delaunay_triangulation_2 Delaunay; 17 | typedef std::pair IPoint; 18 | 19 | using namespace std; 20 | 21 | struct Edge { 22 | int u, v; 23 | long distance; 24 | 25 | bool operator<(const Edge& other) const { 26 | return distance < other.distance; 27 | } 28 | }; 29 | 30 | // For a given component described by the boneDistances, compute the a value 31 | int getA(vector boneDistances, long s) { 32 | auto it = upper_bound(boneDistances.begin(), boneDistances.end(), s); 33 | return distance(boneDistances.begin(), it); 34 | } 35 | 36 | // For a given component described by the boneDistances and the longest edge, compute the q value 37 | long getQ(vector boneDistances, long longestEdge, int k) { 38 | if (boneDistances.size() >= k) { 39 | return max(boneDistances[k - 1], longestEdge); 40 | } 41 | return numeric_limits::max(); 42 | } 43 | 44 | // Strategy: 45 | // - Get graph with Delaunay 46 | // - Use Union-Find to construct connected componets 47 | // - At each merge step compute a and q values 48 | void solve() { 49 | int n, m, k; 50 | long s; // == 4r^2 51 | 52 | cin >> n >> m >> s >> k; 53 | 54 | // Constructe Delaunay triangulation of trees 55 | vector points; 56 | points.reserve(n); 57 | int x, y; 58 | for (int i = 0; i < n; ++i) { 59 | cin >> x >> y; 60 | points.emplace_back(K::Point_2(x, y), i); 61 | } 62 | Delaunay t; 63 | t.insert(points.begin(), points.end()); 64 | 65 | // For each bone: find closest tree 66 | // Keep list for every tree t which contains the distances for all bones that have t as closest tree 67 | vector> bones(n); 68 | for (int i = 0; i < m; ++i) { 69 | cin >> x >> y; 70 | K::Point_2 p(x, y); 71 | auto vertex = t.nearest_vertex(p); 72 | int v = vertex->info(); 73 | auto d = 4 * long(CGAL::squared_distance(p, vertex->point())); 74 | bones[v].push_back(d); 75 | } 76 | // Sort the bone lists 77 | for (int i = 0; i < n; ++i) { 78 | sort(bones[i].begin(), bones[i].end()); 79 | } 80 | 81 | // Extract edges for union find 82 | vector edges; 83 | edges.reserve(3*n); 84 | for (auto e = t.finite_edges_begin(); e != t.finite_edges_end(); ++e) { 85 | int u = e->first->vertex((e->second+1)%3)->info(); 86 | int v = e->first->vertex((e->second+2)%3)->info(); 87 | edges.push_back({u, v, long(t.segment(e).squared_length())}); 88 | } 89 | std::sort(edges.begin(), edges.end()); 90 | 91 | 92 | // Compute solution for before connecting 93 | int a = -1; 94 | long q = numeric_limits::max(); 95 | for (auto bonesOfTree : bones) { 96 | q = min(q, getQ(bonesOfTree, -1, k)); 97 | a = max(a, getA(bonesOfTree, s)); 98 | } 99 | 100 | 101 | // Connect components 102 | boost::disjoint_sets_with_storage<> uf(n); 103 | int n_components = n; 104 | for (auto e : edges) { 105 | int u = e.u; 106 | int v = e.v; 107 | int c1 = uf.find_set(u); 108 | int c2 = uf.find_set(v); 109 | if (c1 != c2) { 110 | 111 | // Link components & merge distances 112 | uf.link(c1, c2); 113 | int c = uf.find_set(c1); 114 | vector dst; 115 | merge(bones[c1].begin(), bones[c1].end(), bones[c2].begin(), bones[c2].end(), back_inserter(dst)); 116 | bones[c] = dst; 117 | 118 | 119 | // Update a & q 120 | q = min(q, getQ(bones[c], e.distance, k)); 121 | if (e.distance <= s) { 122 | a = max(a, getA(bones[c], s)); 123 | } 124 | 125 | if (--n_components == 1) break; 126 | } 127 | } 128 | 129 | cout << a << " " << q << endl; 130 | } 131 | 132 | int main() { 133 | ios_base::sync_with_stdio(false); 134 | int t; 135 | cin >> t; 136 | while (t--) { 137 | solve(); 138 | } 139 | return 0; 140 | } 141 | -------------------------------------------------------------------------------- /src/important_bridges.cpp: -------------------------------------------------------------------------------- 1 | // STL includes 2 | #include 3 | #include 4 | 5 | // BGL includes 6 | #include 7 | #include 8 | 9 | namespace boost { 10 | struct edge_component_t { 11 | enum { num = 555 }; 12 | typedef edge_property_tag kind; 13 | } edge_component; 14 | } 15 | 16 | typedef boost::adjacency_list> graph; 17 | typedef boost::graph_traits::edge_descriptor edge_desc; 18 | typedef boost::graph_traits::vertex_descriptor vertex_desc; 19 | 20 | 21 | using namespace std; 22 | 23 | struct edge { 24 | int u; 25 | int v; 26 | 27 | bool operator<(edge &o) const { 28 | return u < o.u || (u == o.u && v < o.v); 29 | } 30 | }; 31 | 32 | void solve() { 33 | int n; 34 | cin >> n; 35 | int m; 36 | cin >> m; 37 | 38 | graph G(n); 39 | 40 | int u, v; 41 | for (int i = 0; i < m; ++i) { 42 | cin >> u; 43 | cin >> v; 44 | boost::add_edge(u, v, G); 45 | } 46 | 47 | 48 | boost::property_map::type component = get(boost::edge_component, G); 49 | int ncc = biconnected_components(G, component); 50 | 51 | vector> edgesOfComponent(ncc, vector()); 52 | 53 | boost::graph_traits::edge_iterator ei, ei_end; 54 | for (boost::tie(ei, ei_end) = edges(G); ei != ei_end; ++ei) { 55 | edgesOfComponent[component[*ei]].push_back(*ei); 56 | } 57 | 58 | vector result; 59 | for (int i = 0; i < ncc; ++i) { 60 | if (edgesOfComponent[i].size() == 1) { 61 | u = source(edgesOfComponent[i][0], G); 62 | v = target(edgesOfComponent[i][0], G); 63 | if (v < u) { 64 | u = target(edgesOfComponent[i][0], G); 65 | v = source(edgesOfComponent[i][0], G); 66 | } 67 | result.push_back({u, v}); 68 | } 69 | } 70 | sort(result.begin(), result.end()); 71 | 72 | cout << result.size() << endl; 73 | for (auto e : result) { 74 | cout << e.u << " " << e.v << endl; 75 | } 76 | } 77 | 78 | int main() { 79 | int t; 80 | cin >> t; 81 | for (int i = 0; i < t; ++i) { 82 | solve(); 83 | } 84 | } -------------------------------------------------------------------------------- /src/inball.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | typedef int IT; // input type 8 | typedef CGAL::Gmpz ET; // exact type for solver 9 | 10 | typedef CGAL::Quadratic_program Program; 11 | typedef CGAL::Quadratic_program_solution Solution; 12 | 13 | using namespace std; 14 | 15 | void solve(int n, int d) { 16 | 17 | Program lp = Program(CGAL::SMALLER, false, 0, false, 0); 18 | 19 | const int r = d; 20 | 21 | // a.dot(c) + ||a||r <= b 22 | int aij, bi, norm; 23 | for (int i = 0; i < n; ++i) { 24 | norm = 0; 25 | for (int j = 0; j < d; ++j) { 26 | cin >> aij; 27 | norm += aij * aij; 28 | lp.set_a(j, i, aij); 29 | } 30 | norm = sqrt(norm); 31 | lp.set_a(r, i, norm); 32 | 33 | cin >> bi; 34 | lp.set_b(i, bi); 35 | } 36 | 37 | // Radius needs to be positive 38 | lp.set_l(r, true, 0); 39 | 40 | // Maximize radius 41 | lp.set_c(r, -1); 42 | 43 | Solution s = CGAL::solve_linear_program(lp, ET()); 44 | 45 | if (s.is_infeasible()) { 46 | cout << "none" << endl; 47 | } 48 | else if (s.is_unbounded()) { 49 | cout << "inf" << endl; 50 | } 51 | else { 52 | // Implicit round down due to integer division 53 | cout << - s.objective_value_numerator() / s.objective_value_denominator() << endl; 54 | } 55 | } 56 | 57 | int main() { 58 | int n, d; 59 | while (cin >> n && n > 0) { 60 | cin >> d; 61 | solve(n, d); 62 | } 63 | return 0; 64 | } -------------------------------------------------------------------------------- /src/india.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | // Graph Type with nested interior edge properties for Cost Flow Algorithms 13 | typedef boost::adjacency_list_traits traits; 14 | 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 | // Custom edge adder class 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 | //std::cout << from << " -> " << to << ": capacity = " << capacity << ", cost = " << cost << std::endl; 30 | auto c_map = boost::get(boost::edge_capacity, G); 31 | auto r_map = boost::get(boost::edge_reverse, G); 32 | auto w_map = boost::get(boost::edge_weight, G); // new! 33 | const edge_desc e = boost::add_edge(from, to, G).first; 34 | const edge_desc rev_e = boost::add_edge(to, from, G).first; 35 | c_map[e] = capacity; 36 | c_map[rev_e] = 0; // reverse edge has no capacity! 37 | r_map[e] = rev_e; 38 | r_map[rev_e] = e; 39 | w_map[e] = cost; // new assign cost 40 | w_map[rev_e] = -cost; // new negative cost 41 | } 42 | }; 43 | 44 | using namespace std; 45 | 46 | struct elephant { 47 | int x, y, cost, capacity; 48 | }; 49 | 50 | // Compute max flow min cost given a limit for the flow 51 | tuple flowAndCost(int n, int start, int end, vector &elephants, int flowLimit, int budget) { 52 | graph G(n); 53 | edge_adder adder(G); 54 | auto c_map = boost::get(boost::edge_capacity, G); 55 | auto rc_map = boost::get(boost::edge_residual_capacity, G); 56 | 57 | for (auto e : elephants) { 58 | adder.add_edge(e.x, e.y, e.capacity, e.cost); 59 | } 60 | 61 | int source = boost::add_vertex(G); 62 | int target = boost::add_vertex(G); 63 | adder.add_edge(source, start, flowLimit, 0); 64 | adder.add_edge(end, target, flowLimit, 0); 65 | 66 | boost::successive_shortest_path_nonnegative_weights(G, source, target); 67 | int flow = 0; 68 | out_edge_it e, eend; 69 | for(boost::tie(e, eend) = boost::out_edges(boost::vertex(source,G), G); e != eend; ++e) { 70 | flow += c_map[*e] - rc_map[*e]; 71 | } 72 | int cost = boost::find_flow_cost(G); 73 | return {flow, cost}; 74 | } 75 | 76 | // Check if it is feasible to transport numSuitcases suitcases 77 | bool isFeasible(int n, int start, int end, vector &elephants, int numSuitcases, int budget) { 78 | int flow, cost; 79 | tie(flow, cost) = flowAndCost(n, start, end, elephants, numSuitcases, budget); 80 | 81 | if (flow < numSuitcases) { 82 | return false; 83 | } 84 | return cost <= budget; 85 | } 86 | 87 | // Strategy: 88 | // - Binary search to find largest feasible number 89 | void solve() { 90 | int n, m, budget, start, end; 91 | cin >> n >> m >> budget >> start >> end; 92 | 93 | int x, y, cost, capacity; 94 | vector elephants; 95 | elephants.reserve(m); 96 | for (int i = 0; i < m; ++i) { 97 | cin >> x >> y >> cost >> capacity; 98 | elephants.push_back({x, y, cost, capacity}); 99 | } 100 | 101 | // Find an upper bound (what is the max flow?) 102 | int maxFlow = get<0>(flowAndCost(n, start, end, elephants, numeric_limits::max(), budget)); 103 | 104 | // Binary search for highest feasible number of elephants 105 | int a = 0; 106 | int b = maxFlow; 107 | while (a != b) { 108 | int m = a + (b - a + 1) / 2; 109 | 110 | if (isFeasible(n, start, end, elephants, m, budget)) { 111 | a = m; 112 | } 113 | else { 114 | b = m - 1; 115 | } 116 | } 117 | 118 | cout << a << endl; 119 | } 120 | 121 | int main() { 122 | ios_base::sync_with_stdio(false); 123 | int t; 124 | cin >> t; 125 | while (t--) { 126 | solve(); 127 | } 128 | return 0; 129 | } 130 | -------------------------------------------------------------------------------- /src/iron_islands.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | void solve() 9 | { 10 | int n; // number of islands 11 | int k; // number of ironborn men at your disposal 12 | int w; // number of waterways that start at Pyke 13 | cin >> n >> k >> w; 14 | 15 | vector c(n); // number of men required to conquer island i 16 | for (int i = 0; i < n; ++i) { 17 | cin >> c[i]; 18 | } 19 | 20 | vector l(w); 21 | vector> ways(w); // islands along this waterway 22 | for (int i = 0; i < w; ++i) { 23 | cin >> l[i]; 24 | ways[i].resize(l[i]); 25 | for (int j = 0; j < l[i]; ++j) { 26 | cin >> ways[i][j]; 27 | } 28 | } 29 | 30 | 31 | int best = 0; 32 | 33 | // Find solution for single waterway 34 | for (int i = 0; i < w; ++i) { 35 | int a = 0; 36 | int b = 0; 37 | 38 | int sum = c[ways[i][0]]; 39 | 40 | while (a < l[i] && b < l[i]) 41 | { 42 | if (sum == k) { 43 | best = max(best, b - a + 1); 44 | } 45 | 46 | // Update window 47 | if (sum >= k || b == l[i] - 1) { 48 | sum -= c[ways[i][a++]]; 49 | } 50 | else { 51 | sum += c[ways[i][++b]]; 52 | } 53 | } 54 | } 55 | 56 | // Find a solution that includes Pyke 57 | // Idea: 58 | // - compute partial sums for each waterway 59 | // - find two sums that together with c[0] equal k 60 | map sumToDistance; 61 | for (int i = 0; i < w; ++i) { 62 | // Compute partial sums and 63 | vector sums; 64 | sums.push_back(0); 65 | for (int j = 1; j < l[i]; ++j) { 66 | int sum = sums[j - 1] + c[ways[i][j]]; 67 | if (sum + c[0] >= k) { 68 | break; // Sums greater k are irrelevant 69 | } 70 | sums.push_back(sum); 71 | 72 | // find occurrences that satisfies diff 73 | int diff = k - (sum + c[0]); 74 | auto other = sumToDistance.find(diff); 75 | if (other != sumToDistance.end()) { 76 | best = max(best, j + other->second + 1); 77 | } 78 | } 79 | // Add sums of this waterway to map 80 | for (int j = 1; j < sums.size(); ++j) { 81 | // If the sum is already in the map, use the larger distance 82 | sumToDistance[sums[j]] = max(j, sumToDistance[sums[j]]); 83 | } 84 | } 85 | 86 | cout << best << endl; 87 | } 88 | 89 | int main() 90 | { 91 | int t; 92 | cin >> t; 93 | while (t--) 94 | { 95 | solve(); 96 | } 97 | return 0; 98 | } -------------------------------------------------------------------------------- /src/kingdom_defence.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | // Graph Type with nested interior edge properties for flow algorithms 8 | typedef boost::adjacency_list_traits traits; 9 | typedef boost::adjacency_list>>> graph; 13 | 14 | typedef traits::vertex_descriptor vertex_desc; 15 | typedef traits::edge_descriptor edge_desc; 16 | 17 | class edge_adder { 18 | graph &G; 19 | 20 | public: 21 | explicit edge_adder(graph &G) : G(G) {} 22 | 23 | void add_edge(int from, int to, long capacity) { 24 | auto c_map = boost::get(boost::edge_capacity, G); 25 | auto r_map = boost::get(boost::edge_reverse, G); 26 | const auto e = boost::add_edge(from, to, G).first; 27 | const auto rev_e = boost::add_edge(to, from, G).first; 28 | c_map[e] = capacity; 29 | c_map[rev_e] = 0; // reverse edge has no capacity! 30 | r_map[e] = rev_e; 31 | r_map[rev_e] = e; 32 | } 33 | }; 34 | 35 | 36 | using namespace std; 37 | 38 | void solve() { 39 | int n; cin >> n; 40 | int m; cin >> m; 41 | 42 | vector d(n); 43 | int gi, di; 44 | for (int i = 0; i < n; ++i) { 45 | cin >> gi; 46 | cin >> di; 47 | d[i] = di - gi; 48 | } 49 | 50 | graph G(n + 2); 51 | edge_adder adder(G); 52 | 53 | int source = n; 54 | int target = n + 1; 55 | 56 | int u, v, cMin, cMax; 57 | for (int i = 0; i < m; ++i) { 58 | cin >> u; 59 | cin >> v; 60 | cin >> cMin; 61 | cin >> cMax; 62 | 63 | d[u] += cMin; // Increase demand of u 64 | d[v] -= cMin; // Decrease demand of v 65 | int c = cMax - cMin; // Decrease edge capacity of e 66 | 67 | adder.add_edge(u, v, c); 68 | } 69 | 70 | int sumDemands = 0; 71 | for (int v = 0; v < n; ++v) { 72 | if (d[v] < 0) { 73 | adder.add_edge(source, v, -d[v]); 74 | } else if (d[v] > 0) { 75 | sumDemands += d[v]; 76 | adder.add_edge(v, target, d[v]); 77 | } 78 | } 79 | 80 | long flow = boost::push_relabel_max_flow(G, source, target); 81 | cout << (flow == sumDemands ? "yes" : "no") << endl; 82 | } 83 | 84 | int main() { 85 | ios_base::sync_with_stdio(false); 86 | int t; cin >> t; 87 | for (int i = 0; i < t; ++i) { 88 | solve(); 89 | } 90 | } -------------------------------------------------------------------------------- /src/knights.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | // Graph Type with nested interior edge properties for flow algorithms 8 | typedef boost::adjacency_list_traits traits; 9 | typedef boost::adjacency_list>>> graph; 13 | 14 | typedef traits::vertex_descriptor vertex_desc; 15 | typedef traits::edge_descriptor edge_desc; 16 | 17 | class edge_adder { 18 | graph &G; 19 | 20 | public: 21 | explicit edge_adder(graph &G) : G(G) {} 22 | 23 | void add_edge(int from, int to, long capacity) { 24 | auto c_map = boost::get(boost::edge_capacity, G); 25 | auto r_map = boost::get(boost::edge_reverse, G); 26 | const auto e = boost::add_edge(from, to, G).first; 27 | const auto rev_e = boost::add_edge(to, from, G).first; 28 | c_map[e] = capacity; 29 | c_map[rev_e] = 0; // reverse edge has no capacity! 30 | r_map[e] = rev_e; 31 | r_map[rev_e] = e; 32 | } 33 | }; 34 | 35 | 36 | using namespace std; 37 | 38 | int index(int row, int col, bool in, int cols) { 39 | return 2 * (row * cols + col) + in; 40 | } 41 | 42 | void solve() { 43 | int cols; cin >> cols; 44 | int rows; cin >> rows; 45 | int k; cin >> k; 46 | int c; cin >> c; 47 | 48 | graph G(2 * rows * cols); 49 | edge_adder adder(G); 50 | 51 | if (cols == 0 || rows == 0 || k == 0 || c == 0) { 52 | cout << 0 << endl; 53 | return; 54 | } 55 | 56 | // Set up graph 57 | for (int row = 0; row < rows; ++row) { 58 | for (int col = 0; col < cols; ++col) { 59 | // In to out vertex 60 | adder.add_edge(index(row, col, true, cols), index(row, col, false, cols), c); 61 | 62 | // Neighbors 63 | if (row > 0) 64 | adder.add_edge(index(row - 1, col, false, cols), index(row, col, true, cols), 1); 65 | if (row < rows - 1) 66 | adder.add_edge(index(row + 1, col, false, cols), index(row, col, true, cols), 1); 67 | if (col > 0) 68 | adder.add_edge(index(row, col - 1, false, cols), index(row, col, true, cols), 1); 69 | if (col < cols - 1) 70 | adder.add_edge(index(row, col + 1, false, cols), index(row, col, true, cols), 1); 71 | 72 | } 73 | } 74 | 75 | // Set up target 76 | vertex_desc target = boost::add_vertex(G); 77 | for (int row = 0; row < rows; ++row) { 78 | adder.add_edge(index(row, 0, false, cols), target, 1); 79 | adder.add_edge(index(row, cols - 1, false, cols), target, 1); 80 | } 81 | for (int col = 0; col < cols; ++col) { 82 | adder.add_edge(index(0, col, false, cols), target, 1); 83 | adder.add_edge(index(rows - 1, col, false, cols), target, 1); 84 | } 85 | 86 | // Set up source 87 | vertex_desc source = boost::add_vertex(G); 88 | int row, col; 89 | for (int i = 0; i < k; ++i) { 90 | cin >> col; 91 | cin >> row; 92 | adder.add_edge(source, index(row, col, true, cols), 1); 93 | } 94 | 95 | 96 | long flow = boost::push_relabel_max_flow(G, source, target); 97 | cout << flow << endl; 98 | } 99 | 100 | int main() { 101 | ios_base::sync_with_stdio(false); 102 | int t; cin >> t; 103 | for (int i = 0; i < t; ++i) { 104 | solve(); 105 | } 106 | } -------------------------------------------------------------------------------- /src/lannister.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | typedef long IT; 10 | typedef CGAL::Gmpz ET; 11 | 12 | typedef CGAL::Quadratic_program Program; 13 | typedef CGAL::Quadratic_program_solution Solution; 14 | 15 | using namespace std; 16 | 17 | void solve() 18 | { 19 | int n; // Number of nobel houses 20 | int m; // Number of common houses 21 | long s; // Maximum allowable sum of lengths of all sewage pipes, -1 means unbounded 22 | 23 | cin >> n >> m >> s; 24 | 25 | vector nx(n); // x coordinates of nobel houses 26 | vector ny(n); // y coordinates of nobel houses 27 | long nxSum = 0; 28 | long nySum = 0; 29 | for (int i = 0; i < n; ++i) { 30 | cin >> nx[i] >> ny[i]; 31 | nxSum += nx[i]; 32 | nySum += ny[i]; 33 | } 34 | 35 | vector cx(m); // x coordinates of common houses 36 | vector cy(m); // y coordinates of common houses 37 | long cxSum = 0; 38 | long cySum = 0; 39 | for (int i = 0; i < m; ++i) { 40 | cin >> cx[i] >> cy[i]; 41 | cxSum += cx[i]; 42 | cySum += cy[i]; 43 | } 44 | 45 | // Solve it as a linear program 46 | Program lp (CGAL::SMALLER, false, 0, false, 0); 47 | const int a = 0; 48 | const int b = 1; 49 | const int c = 2; 50 | const int d = 3; 51 | const int l = 4; 52 | 53 | int row = 0; 54 | 55 | // Nobel houses need to left of l1: ax + by + c 56 | for (int i = 0; i < n; ++i) { 57 | // ax + by + c <= 0 58 | lp.set_a(a, row, nx[i]); 59 | lp.set_a(b, row, ny[i]); 60 | lp.set_a(c, row, 1); 61 | ++row; 62 | } 63 | 64 | // Common houses need to right of l1 65 | for (int i = 0; i < m; ++i) { 66 | // ax + by + c >= 0 <=> -ax -by -c <= 0 67 | lp.set_a(a, row, -cx[i]); 68 | lp.set_a(b, row, -cy[i]); 69 | lp.set_a(c, row, -1); 70 | ++row; 71 | } 72 | 73 | // enforce a != 0 by setting a == 1 74 | lp.set_l(a, true, 1); 75 | lp.set_u(a, true, 1); 76 | 77 | 78 | // Solve the LP 79 | Solution solution = CGAL::solve_linear_program(lp, ET()); 80 | 81 | if (solution.is_infeasible()) { 82 | cout << "Yuck!" << endl; 83 | return; 84 | } 85 | 86 | // Check Tywin's constraint 87 | // The sum of the lengths of all sewage pipes must not exceed s 88 | if (s != -1) { 89 | lp.set_a(b, row, cySum - nySum); 90 | lp.set_a(c, row, m - n); 91 | lp.set_b(row, s - (cxSum - nxSum)); 92 | row++; 93 | 94 | solution = CGAL::solve_linear_program(lp, ET()); 95 | 96 | if (solution.is_infeasible()) { 97 | cout << "Bankrupt!" << endl; 98 | return; 99 | } 100 | } 101 | 102 | // Jamie's optimization: 103 | // Minimize the length l of the longest fresh water pipe 104 | for (int i = 0; i < n; ++i) { 105 | // length of fresh pipe <= l 106 | lp.set_a(b, row, nx[i]); 107 | lp.set_a(d, row, 1); 108 | lp.set_a(l, row, -1); 109 | lp.set_b(row, ny[i]); 110 | row++; 111 | lp.set_a(b, row, -nx[i]); 112 | lp.set_a(d, row, -1); 113 | lp.set_a(l, row, -1); 114 | lp.set_b(row, -ny[i]); 115 | row++; 116 | } 117 | for (int i = 0; i < m; ++i) { 118 | // length of fresh pipe <= l 119 | lp.set_a(b, row, cx[i]); 120 | lp.set_a(d, row, 1); 121 | lp.set_a(l, row, -1); 122 | lp.set_b(row, cy[i]); 123 | row++; 124 | lp.set_a(b, row, -cx[i]); 125 | lp.set_a(d, row, -1); 126 | lp.set_a(l, row, -1); 127 | lp.set_b(row, -cy[i]); 128 | row++; 129 | } 130 | 131 | // Ensure l is positive 132 | lp.set_l(l, true, 0); 133 | 134 | // Minimize l 135 | lp.set_c(l, 1); 136 | 137 | solution = CGAL::solve_linear_program(lp, ET()); 138 | 139 | cout << fixed << setprecision(0) << ceil(CGAL::to_double(solution.objective_value())) << endl; 140 | } 141 | 142 | 143 | int main() { 144 | ios_base::sync_with_stdio(false); 145 | int t; 146 | cin >> t; 147 | while (t--) { 148 | solve(); 149 | } 150 | return 0; 151 | } -------------------------------------------------------------------------------- /src/legions.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | typedef int IT; // input type 9 | typedef CGAL::Gmpz ET; // exact type for solver 10 | 11 | typedef CGAL::Quadratic_program Program; 12 | typedef CGAL::Quadratic_program_solution Solution; 13 | 14 | using namespace std; 15 | 16 | void solve() { 17 | int xs, ys, n; 18 | cin >> xs >> ys >> n; 19 | 20 | Program lp = Program(CGAL::SMALLER, false, 0, false, 0); 21 | 22 | int x = 0; 23 | int y = 1; 24 | int r = 2; 25 | 26 | long a, b, c, v; 27 | for (int i = 0; i < n; ++i) { 28 | cin >> a >> b >> c >> v; 29 | 30 | long valStart = a * xs + b * ys + c; 31 | if (valStart > 0) { 32 | a *= -1; 33 | b *= -1; 34 | c *= -1; 35 | } 36 | 37 | long sqrtTerm = long(sqrt(a * a + b * b)); 38 | 39 | lp.set_a(x, i, a); 40 | lp.set_a(y, i, b); 41 | lp.set_a(r, i, v * sqrtTerm); 42 | 43 | lp.set_b(i, -c); 44 | } 45 | 46 | // Radius needs to be positive 47 | lp.set_l(r, true, 0); 48 | 49 | // Maximize radius 50 | lp.set_c(r, -1); 51 | 52 | Solution s = CGAL::solve_linear_program(lp, ET()); 53 | 54 | if (s.is_infeasible()) { 55 | cout << "none" << endl; 56 | } 57 | else if (s.is_unbounded()) { 58 | cout << "inf" << endl; 59 | } 60 | else { 61 | // Implicit round down due to integer division 62 | cout << - s.objective_value_numerator() / s.objective_value_denominator() << endl; 63 | } 64 | } 65 | 66 | int main() { 67 | ios_base::sync_with_stdio(false); 68 | int t; cin >> t; 69 | for (int i = 0; i < t; ++i) { 70 | solve(); 71 | } 72 | return 0; 73 | } -------------------------------------------------------------------------------- /src/lestrade.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | typedef int IT; 15 | typedef CGAL::Gmpz ET; 16 | 17 | typedef CGAL::Quadratic_program Program; 18 | typedef CGAL::Quadratic_program_solution Solution; 19 | 20 | typedef CGAL::Exact_predicates_inexact_constructions_kernel K; 21 | typedef int Index; 22 | typedef CGAL::Triangulation_vertex_base_with_info_2 Vb; 23 | typedef CGAL::Triangulation_face_base_2 Fb; 24 | typedef CGAL::Triangulation_data_structure_2 Tds; 25 | typedef CGAL::Delaunay_triangulation_2 DT; 26 | typedef std::pair IPoint; 27 | 28 | using namespace std; 29 | 30 | struct gangMember { 31 | int u, v, w; 32 | }; 33 | 34 | 35 | // A straight forward LP with an additional Delaunay Triangulation 36 | // to figure out which agent is observing which gang member. 37 | void solve() { 38 | 39 | int z, u, v, w; 40 | cin >> z >> u >> v >> w; 41 | 42 | int a, g; 43 | cin >> a >> g; 44 | 45 | // Read gang and construct DT of positions of gang members 46 | int x, y, ui, vi, wi; 47 | vector gang(g); 48 | vector pts(g); 49 | for (int i = 0; i < g; ++i) { 50 | cin >> x >> y >> ui >> vi >> wi; 51 | pts[i] = {{x, y}, i}; 52 | gang[i] = {ui, vi, wi}; 53 | } 54 | 55 | DT dt; 56 | dt.insert(pts.begin(), pts.end()); 57 | 58 | // Read agents and assign them to observe a gang member. 59 | // To make things easier, we simply store the observation cost directly 60 | // to the observed gang member. 61 | int zi; 62 | vector observationCost(g, numeric_limits::max()); 63 | for (int i = 0; i < a; ++i) { 64 | cin >> x >> y >> zi; 65 | // An agent always observes the nearest gang member 66 | int nearest = dt.nearest_vertex(K::Point_2(x, y))->info(); 67 | // If a gang member is observed by multiple agents, we want to use the cheapest agent 68 | observationCost[nearest] = min(zi, observationCost[nearest]); 69 | } 70 | 71 | // Solve a LP with the inequalites (1-3) and objective (4) 72 | // (1) sum hi*ui >= u 73 | // (2) sum hi*vi >= v 74 | // (3) sum hi*wi >= w 75 | // (4) min sum hi*zi 76 | Program lp (CGAL::LARGER, true, 0, true, 24); 77 | 78 | lp.set_b(0, u); // (1) 79 | lp.set_b(1, v); // (2) 80 | lp.set_b(2, w); // (3) 81 | 82 | int hi = 0; 83 | for (int i = 0; i < g; ++i) { 84 | zi = observationCost[i]; 85 | if (zi == numeric_limits::max()) { 86 | continue; // This gang member is not observed by any agent 87 | } 88 | 89 | lp.set_a(hi, 0, gang[i].u); // (1) 90 | lp.set_a(hi, 1, gang[i].v); // (2) 91 | lp.set_a(hi, 2, gang[i].w); // (3) 92 | 93 | lp.set_c(hi, zi); // (4) 94 | 95 | hi++; 96 | } 97 | 98 | Solution solution = CGAL::solve_linear_program(lp, ET()); 99 | 100 | // Holmes gets hired if the solution is infeasible or mor expensive than Holmes fee 101 | if (solution.is_infeasible() || solution.objective_value() > z) { 102 | cout << "H" << endl; 103 | } 104 | else { 105 | cout << "L" << endl; 106 | } 107 | } 108 | 109 | int main() 110 | { 111 | ios_base::sync_with_stdio(false); 112 | int t; cin >> t; 113 | while (t--) { 114 | solve(); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/marathon.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | typedef boost::adjacency_list_traits traits; 12 | typedef boost::adjacency_list>>> graph; 16 | 17 | typedef traits::vertex_descriptor vertex_desc; 18 | typedef traits::edge_descriptor edge_desc; 19 | typedef boost::adjacency_list > weighted_graph; 21 | typedef boost::property_map::type weight_map; 22 | 23 | // Custom edge adder class, highly recommended 24 | class edge_adder { 25 | graph &G; 26 | 27 | public: 28 | explicit edge_adder(graph &G) : G(G) {} 29 | 30 | void add_edge(int from, int to, long capacity) { 31 | auto c_map = boost::get(boost::edge_capacity, G); 32 | auto r_map = boost::get(boost::edge_reverse, G); 33 | const auto e = boost::add_edge(from, to, G).first; 34 | const auto rev_e = boost::add_edge(to, from, G).first; 35 | c_map[e] = capacity; 36 | c_map[rev_e] = 0; // reverse edge has no capacity! 37 | r_map[e] = rev_e; 38 | r_map[rev_e] = e; 39 | } 40 | }; 41 | 42 | using namespace std; 43 | 44 | struct edge { 45 | int u; 46 | int v; 47 | int length; 48 | int width; 49 | }; 50 | 51 | // Strategy: 52 | // - Find all edges that are part of some shortest path 53 | // - Run a max-flow algorithm on those edges 54 | void solve() { 55 | int n, m, s, f; 56 | cin >> n >> m >> s >> f; 57 | 58 | // Dijkstra Graph 59 | weighted_graph G(n); 60 | 61 | // Read neighbors 62 | vector edges; 63 | edges.reserve(m); 64 | int u, v, length, width; 65 | for (int i = 0; i < m; ++i) { 66 | cin >> u >> v >> width >> length; 67 | boost::add_edge(u, v, length, G); 68 | edges.push_back({u, v, length, width}); 69 | } 70 | 71 | // Run dijkstra 72 | std::vector d(n); 73 | boost::dijkstra_shortest_paths(G, s, boost::distance_map(boost::make_iterator_property_map( d.begin(), boost::get(boost::vertex_index, G)))); 74 | 75 | // Flow graph 76 | graph gFlow(n); 77 | edge_adder adder(gFlow); 78 | 79 | 80 | // Find edges on a shortest path 81 | vector shortestPathEdges; 82 | for (auto e : edges) { 83 | int diff = d[e.v] - d[e.u]; 84 | if (e.length == diff) { 85 | adder.add_edge(e.u, e.v, e.width); 86 | } 87 | else if (e.length == -diff) { 88 | adder.add_edge(e.v, e.u, e.width); 89 | } 90 | } 91 | 92 | // Compute flow 93 | long flow = boost::push_relabel_max_flow(gFlow, s, f); 94 | cout << flow << endl; 95 | } 96 | 97 | int main() { 98 | ios_base::sync_with_stdio(false); 99 | int t; cin >> t; 100 | while (t--) 101 | { 102 | solve(); 103 | } 104 | return 0; 105 | } -------------------------------------------------------------------------------- /src/maximizeit.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | typedef int IT; // input type 8 | typedef CGAL::Gmpz ET; // exact type for solver 9 | 10 | typedef CGAL::Quadratic_program Program; 11 | typedef CGAL::Quadratic_program_solution Solution; 12 | 13 | using namespace std; 14 | 15 | void solve(int p) { 16 | int a, b; 17 | cin >> a; 18 | cin >> b; 19 | 20 | const int x = 0; 21 | const int y = 1; 22 | const int z = 2; 23 | 24 | if (p == 1) { 25 | Program lp = Program(CGAL::SMALLER, true, 0, false, 0); 26 | lp.set_a(x, 0, 1); lp.set_a(y, 0, 1); lp.set_b(0, 4); // x + y <= 4 27 | lp.set_a(x, 1, 4); lp.set_a(y, 1, 2); lp.set_b(1, a * b); // 4x + 2y <= ab 28 | lp.set_a(x, 2, -1); lp.set_a(y, 2, 1); lp.set_b(2, 1); // -x + y <= 1 29 | 30 | // max by - ax <=> min -(by - ax) = ax - by 31 | lp.set_c(x, a); 32 | lp.set_c(y, -b); 33 | 34 | Solution s = CGAL::solve_linear_program(lp, ET()); 35 | 36 | if (s.is_infeasible()) { 37 | cout << "no" << endl; 38 | } else { 39 | cout << setprecision(0) << fixed << floor(CGAL::to_double(-s.objective_value())) << endl; 40 | } 41 | } 42 | else { 43 | Program lp = Program(CGAL::SMALLER, false, 0, true, 0); 44 | lp.set_a(x, 0, -1); lp.set_a(y, 0, -1); lp.set_b(0, 4); // -x - y <= 4 45 | lp.set_a(x, 1, -4); lp.set_a(y, 1, -2); lp.set_a(z, 1, -1); lp.set_b(1, a * b); // -4x - 2y - z <= ab 46 | lp.set_a(x, 2, 1); lp.set_a(y, 2, -1); lp.set_b(2, 1); // x - y <= 1 47 | 48 | // min ax + by + z 49 | lp.set_c(x, a); 50 | lp.set_c(y, b); 51 | lp.set_c(z, 1); 52 | 53 | Solution s = CGAL::solve_linear_program(lp, ET()); 54 | if (s.is_infeasible()) { 55 | cout << "no" << endl; 56 | } else { 57 | cout << setprecision(0) << fixed << ceil(CGAL::to_double(s.objective_value())) << endl; 58 | } 59 | } 60 | 61 | 62 | } 63 | 64 | int main() { 65 | int p; 66 | while (cin >> p && p != 0) { 67 | solve(p); 68 | } 69 | return 0; 70 | } -------------------------------------------------------------------------------- /src/meereen.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | int mask; 10 | int differenceOffset = 12; 11 | 12 | struct Queue 13 | { 14 | int a, b, c; 15 | 16 | // Count the number of distinct elements in the queue 17 | int numDistinct() { 18 | set abc = {0, a, b, c}; 19 | return abc.size() - 1; 20 | } 21 | 22 | // Insert a new value and return a new queue 23 | Queue insert(int value) { 24 | return {value, a, b}; 25 | } 26 | 27 | // Encode as int 28 | int encode() const { 29 | return a + (b << 3) + (c << 6); 30 | } 31 | }; 32 | 33 | // Decode a queue from an integer value 34 | Queue decodeQueue(int value) { 35 | int a = value & 7; 36 | int b = (value >> 3) & 7; 37 | int c = 0; // We do not save the last element 38 | return {a, b, c}; 39 | } 40 | 41 | 42 | struct State { 43 | Queue north; 44 | Queue south; 45 | int difference; 46 | 47 | // Encode as int 48 | int encode() const { 49 | return ((difference + differenceOffset) << 18) + ((south.encode() & mask) << 9) + (north.encode() & mask); 50 | } 51 | 52 | // Compute the score for a given queue 53 | int computeScore(bool useNorth) { 54 | int numDistinct = useNorth ? north.numDistinct() : south.numDistinct(); 55 | return numDistinct * 1000 - int(pow(2, abs(difference))); 56 | } 57 | }; 58 | 59 | // Decode a state from an integer value 60 | State decodeState(int value) { 61 | int north = value & mask; 62 | int south = (value >> 9) & mask; 63 | int difference = (value >> 18) - differenceOffset; 64 | return {decodeQueue(north), decodeQueue(south), difference}; 65 | } 66 | 67 | // Insert a state into the states map if the score is positive 68 | void insertOrUpdate(State state, int score, int prevScore, map &states) { 69 | if (score < 0) { 70 | return; 71 | } 72 | int encoded = state.encode(); 73 | states[encoded] = max(prevScore + score, states[encoded]); 74 | } 75 | 76 | void solve() { 77 | 78 | int n; // Number of fighters 79 | int k; // Number of different types of fighters, 2 <= k <= 4 80 | int m; // Number of fighters the audience can remember, 2 <= m <= 3 81 | cin >> n >> k >> m; 82 | 83 | vector fighters(n); // Queue of fighters 84 | for (int i = 0; i < n; ++i) { 85 | cin >> fighters[i]; 86 | fighters[i]++; // Offset type by one to reserve 0 for empty 87 | } 88 | 89 | int b = 3 * (m - 1); // Number of bits needed to encode a queue 90 | mask = (1 << b) - 1; // In binary: '1' repeated b times 91 | 92 | 93 | State initalState = {{0, 0, 0}, {0, 0, 0}, 0}; 94 | 95 | map currentStates; 96 | currentStates[initalState.encode()] = 0; 97 | 98 | for (int fighter : fighters) { 99 | map nextStates; 100 | for (auto entry : currentStates) { 101 | int score = entry.second; 102 | auto state = decodeState(entry.first); 103 | 104 | State nextNorth = {state.north.insert(fighter), state.south, state.difference - 1}; 105 | State nextSouth = {state.north, state.south.insert(fighter), state.difference + 1}; 106 | 107 | int scoreNorth = nextNorth.computeScore(true); 108 | int scoreSouth = nextSouth.computeScore(false); 109 | 110 | insertOrUpdate(nextNorth, scoreNorth, score, nextStates); 111 | insertOrUpdate(nextSouth, scoreSouth, score, nextStates); 112 | } 113 | currentStates = nextStates; 114 | } 115 | 116 | 117 | // Find max value 118 | int maxValue = -1; 119 | for (auto entry : currentStates) { 120 | maxValue = max(entry.second, maxValue); 121 | } 122 | 123 | cout << maxValue << endl; 124 | 125 | } 126 | 127 | int main() { 128 | ios_base::sync_with_stdio(false); 129 | int t; 130 | cin >> t; 131 | while (t--) { 132 | solve(); 133 | } 134 | return 0; 135 | } -------------------------------------------------------------------------------- /src/motorcycles.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | typedef CGAL::Exact_predicates_inexact_constructions_kernel EPIC; 8 | typedef EPIC::Point_2 P; 9 | typedef EPIC::Line_2 L; 10 | typedef EPIC::Ray_2 R; 11 | 12 | using namespace std; 13 | 14 | struct Biker { 15 | int i; // original index 16 | long y0, x1, y1; // ray description 17 | R ray; // trajectory of the biker 18 | L slope; // Slope for determining who keeps on driving 19 | 20 | Biker() {} 21 | Biker(int i, long y0, long x1, long y1) : i(i), y0(y0), x1(x1), y1(y1), ray(R(P(0, y0), P(x1, y1))) { 22 | if (y0 < y1) { 23 | slope = L(P(0, y0), P(x1, y1)); 24 | } 25 | else { 26 | slope = L(P(0, -y0), P(x1, -y1)); // Reflect around origin to always get a positive slope 27 | } 28 | } 29 | 30 | // Sort by y0 value 31 | bool operator<(const Biker &rhs) { 32 | return y0 < rhs.y0; 33 | } 34 | 35 | // Returns true if this biker meets other and continues driving 36 | bool lives(const Biker &other) { 37 | auto result = CGAL::compare_slope(slope, other.slope); 38 | if (result == CGAL::Comparison_result::SMALLER || (result == CGAL::Comparison_result::EQUAL && y0 < other.y0)) { 39 | return true; 40 | } 41 | return false; 42 | } 43 | }; 44 | 45 | 46 | // Strategy: 47 | // - Sort by start offset (i.e. y0) 48 | // - Check against previous bikers only, with early termination 49 | void solve() { 50 | int n; cin >> n; 51 | 52 | vector b(n); 53 | long y0, x1, y1; 54 | for (int i = 0; i < n; ++i) { 55 | cin >> y0 >> x1 >> y1; 56 | b[i] = Biker(i, y0, x1, y1); 57 | } 58 | 59 | // Sort according to y0 60 | sort(b.begin(), b.end()); 61 | 62 | // Compute who rides forever 63 | vector forever(n, true); 64 | for (int i = 0; i < n; ++i) { 65 | 66 | // Check against previous bikers 67 | for (int j = i - 1; j >= 0; --j) { 68 | 69 | // Ignore "dead" bikers 70 | if (!forever[b[j].i]) { 71 | continue; 72 | } 73 | 74 | // Does not intersect previous => No further tests needed 75 | if (!CGAL::do_intersect(b[i].ray, b[j].ray)) { 76 | break; 77 | } 78 | 79 | // Evaluate who keeps on driving 80 | if (b[i].lives(b[j])) { 81 | forever[b[j].i] = false; 82 | } 83 | else { 84 | forever[b[i].i] = false; 85 | break; // Driver i stops, we do not need to check against previous bikers anymore 86 | } 87 | } 88 | } 89 | 90 | // Output solution 91 | for (int i = 0; i < n; ++i) { 92 | if (forever[i]) { 93 | cout << i << " "; 94 | } 95 | } 96 | cout << endl; 97 | 98 | } 99 | 100 | 101 | int main() { 102 | ios_base::sync_with_stdio(false); 103 | int t; 104 | cin >> t; 105 | while (t--) { 106 | solve(); 107 | } 108 | return 0; 109 | } -------------------------------------------------------------------------------- /src/moving_books.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | // Strategy: 8 | // Sort strengths and weights in ascending order 9 | // For i = 1..n: 10 | // - Take all boxes that are too heavy for everyone before, but not too heavy for person i 11 | // - If person i carries less than the person carrying the most, take over boxes 12 | void solve() { 13 | int n, m; 14 | cin >> n >> m; 15 | 16 | // Read strengths 17 | vector s(n); 18 | for (int i = 0; i < n; ++i) { 19 | cin >> s[i]; 20 | } 21 | 22 | // Read weights 23 | vector w(m); 24 | for (int i = 0; i < m; ++i) { 25 | cin >> w[i]; 26 | } 27 | 28 | // Sort strengths and weights 29 | sort(s.begin(), s.end()); 30 | sort(w.begin(), w.end()); 31 | 32 | // If the heaviest box is to heavy for the strongest person, it is impossible 33 | if (s[n - 1] < w[m - 1]) { 34 | cout << "impossible" << endl; 35 | return; 36 | } 37 | 38 | // Keep track what the maximum amount is someone carries 39 | int maxBoxes = 0; 40 | 41 | int j = 0; 42 | vector numPeople(m + 1, 0); // How many people carry exactly j boxes 43 | for (int i = 0; i < n; ++i) { 44 | 45 | // Slide over boxes for counting 46 | int count = 0; 47 | while (j < m && w[j] <= s[i]) { 48 | ++j; 49 | ++count; 50 | } 51 | numPeople[count]++; 52 | 53 | // A new maximum 54 | if (count >= maxBoxes || i == 0) { 55 | maxBoxes = count; 56 | } 57 | 58 | // Person i can take over boxes of other people 59 | else { 60 | // While person i has some spare capacity 61 | while (count < maxBoxes) { 62 | // Take one box form each person that is already carrying the maxBoxes 63 | // Make sure not to take on too many boxes 64 | int delta = min(numPeople[maxBoxes], maxBoxes - count); 65 | 66 | // one person now carries delta additional boxes 67 | numPeople[count] -= 1; 68 | numPeople[count + delta] += 1; 69 | 70 | // delta people now carry one box less 71 | numPeople[maxBoxes] -= delta; 72 | numPeople[maxBoxes - 1] += delta; 73 | 74 | // Update count for current person 75 | count += delta; 76 | 77 | // If there is no one left at full capacity, reduce capacity 78 | if (numPeople[maxBoxes] == 0) { 79 | maxBoxes--; 80 | } 81 | } 82 | } 83 | } 84 | 85 | // Calculate time 86 | int time = 3 * maxBoxes - 1; 87 | cout << time << endl; 88 | 89 | } 90 | 91 | int main() { 92 | ios_base::sync_with_stdio(false); 93 | int t; cin >> t; 94 | while (t--) { 95 | solve(); 96 | } 97 | return 0; 98 | } -------------------------------------------------------------------------------- /src/moving_books_binary_search.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | vector s; 8 | vector w; 9 | 10 | bool isFeasible(int k) { 11 | 12 | long n = s.size(); 13 | long m = w.size(); 14 | 15 | if (n * k < m) { 16 | return false; 17 | } 18 | 19 | int j = m - 1; 20 | for (int i = n - 1; i >= 0 && j >= 0; --i) { 21 | if (s[i] < w[j]) { 22 | return false; 23 | } 24 | j -= k; 25 | } 26 | 27 | return true; 28 | } 29 | 30 | void solve() { 31 | int n, m; 32 | cin >> n >> m; 33 | 34 | s = vector(n); 35 | for (int i = 0; i < n; ++i) { 36 | cin >> s[i]; 37 | } 38 | 39 | w = vector(m); 40 | for (int i = 0; i < m; ++i) { 41 | cin >> w[i]; 42 | } 43 | 44 | sort(s.begin(), s.end()); 45 | sort(w.begin(), w.end()); 46 | 47 | if (w.back() > s.back()) { 48 | cout << "impossible" << endl; 49 | return; 50 | } 51 | 52 | int a = 1; 53 | int b = w.size(); 54 | 55 | while (a != b) { 56 | int m = (a + b) / 2; 57 | if (isFeasible(m)) { 58 | b = m; 59 | } 60 | else { 61 | a = m + 1; 62 | } 63 | } 64 | 65 | cout << (3 * a - 1) << endl; 66 | } 67 | 68 | int main() { 69 | ios_base::sync_with_stdio(false); 70 | int t; 71 | cin >> t; 72 | while (t--) { 73 | solve(); 74 | } 75 | return 0; 76 | } -------------------------------------------------------------------------------- /src/new_york.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | 10 | // To make the code more readable, we do not want to 11 | // pass all variables to the recursive function 12 | vector> children; 13 | vector parents; 14 | vector starts; 15 | vector h; 16 | int n, m, k; 17 | 18 | // Current path & temperatures of this path 19 | deque path; 20 | multiset pathTemperatures; 21 | 22 | 23 | // General idea: 24 | // Perform a "sliding window" over the tree. 25 | // I.e. we will always keep the current path and the corresponding temperatures. 26 | // When we discover a new child, we will append it (and its temperature) to the path. 27 | // When the path gets to long, we will remove the first element. 28 | // When we go back up in the recursion again, we will remove the current element (last element of path) 29 | // and add back the parent of the first element (if it exists, i.e. if first element != tree root) 30 | void findStarts(int u) { 31 | 32 | // Append newly discovered 33 | path.push_back(u); 34 | pathTemperatures.insert(h[u]); 35 | 36 | // If path has gotten too long, remove first element of path 37 | if (path.size() > m) { 38 | int front = path[0]; 39 | path.pop_front(); 40 | pathTemperatures.erase(pathTemperatures.find(h[front])); 41 | } 42 | 43 | // If the path has the desired length, we check if it is feasible 44 | if (path.size() == m) { 45 | // The first element of a multiset is the smallest, the last the largest 46 | int minVal = *pathTemperatures.begin(); 47 | int maxVal = *pathTemperatures.rbegin(); 48 | if (maxVal - minVal <= k) { 49 | starts.push_back(path[0]); 50 | } 51 | } 52 | 53 | // Explore children (recursive call) 54 | for (auto v : children[u]) { 55 | findStarts(v); 56 | } 57 | 58 | // Remove current element from path 59 | path.pop_back(); 60 | pathTemperatures.erase(pathTemperatures.find(h[u])); 61 | 62 | // Restore first element of path 63 | if (path[0] != 0) { 64 | int parent = parents[path[0]]; 65 | path.push_front(parent); 66 | pathTemperatures.insert(h[parent]); 67 | } 68 | } 69 | 70 | void solve() { 71 | // Read input 72 | cin >> n >> m >> k; 73 | 74 | // Read temperatures 75 | h = vector(n); 76 | for (int i = 0; i < n; ++i) { 77 | cin >> h[i]; 78 | } 79 | 80 | // Read tree 81 | children = vector>(n); 82 | parents = vector(n); 83 | int u, v; 84 | for (int i = 0; i < n - 1; ++i) { 85 | cin >> u >> v; 86 | children[u].push_back(v); 87 | parents[v] = u; 88 | } 89 | 90 | // Initialize path and result container 91 | path = deque(); 92 | pathTemperatures = multiset(); 93 | starts = vector(); // Result container 94 | 95 | // Compute solution 96 | findStarts(0); 97 | 98 | // Ensure elements are ordered 99 | sort(starts.begin(), starts.end()); 100 | 101 | // Print solution 102 | int prevStart = -1; 103 | for (auto start : starts) { 104 | if (start != prevStart) { // Avoid duplicates 105 | prevStart = start; 106 | cout << start << " "; 107 | } 108 | } 109 | 110 | // No feasible path 111 | if (starts.empty()) { 112 | cout << "Abort mission"; 113 | } 114 | cout << endl; 115 | } 116 | 117 | 118 | int main() { 119 | ios_base::sync_with_stdio(false); 120 | int t; cin >> t; 121 | for (int i = 0; i < t; ++i) { 122 | solve(); 123 | } 124 | return 0; 125 | } -------------------------------------------------------------------------------- /src/octopussy.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | void solve() { 8 | int n; cin >> n; 9 | vector mins(n); 10 | for (int i = 0; i < n; ++i) { 11 | cin >> mins[i]; 12 | } 13 | 14 | for (int i = 0; i <= (n - 3) / 2; ++i) { 15 | mins[2 * i + 1] = min(mins[2 * i + 1], mins[i] - 1); 16 | mins[2 * i + 2] = min(mins[2 * i + 2], mins[i] - 1); 17 | } 18 | 19 | sort(mins.begin(), mins.end()); 20 | 21 | bool success = true; 22 | for (int i = 0; i < n; ++i) { 23 | if (mins[i] <= i) { 24 | success = false; 25 | break; 26 | } 27 | } 28 | 29 | if (success) { 30 | cout << "yes"; 31 | } 32 | else { 33 | cout << "no"; 34 | } 35 | cout << endl; 36 | 37 | } 38 | 39 | int main() { 40 | ios_base::sync_with_stdio(false); 41 | int t; cin >> t; 42 | for (int i = 0; i < t; ++i) { 43 | solve(); 44 | } 45 | } -------------------------------------------------------------------------------- /src/placing_knights.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | typedef boost::adjacency_list_traits traits; 6 | typedef boost::adjacency_list>>> 10 | graph; 11 | 12 | typedef traits::vertex_descriptor vertex_desc; 13 | typedef traits::edge_descriptor edge_desc; 14 | 15 | class edge_adder 16 | { 17 | graph &G; 18 | 19 | public: 20 | explicit edge_adder(graph &G) : G(G) {} 21 | 22 | void add_edge(int from, int to, long capacity) 23 | { 24 | auto c_map = boost::get(boost::edge_capacity, G); 25 | auto r_map = boost::get(boost::edge_reverse, G); 26 | const auto e = boost::add_edge(from, to, G).first; 27 | const auto rev_e = boost::add_edge(to, from, G).first; 28 | c_map[e] = capacity; 29 | c_map[rev_e] = 0; // reverse edge has no capacity! 30 | r_map[e] = rev_e; 31 | r_map[rev_e] = e; 32 | } 33 | 34 | void add_edge_if_exists(int i1, int j1, int i2, int j2, int n, std::vector& present) { 35 | int from = i1 * n + j1; 36 | int to = i2 * n + j2; 37 | if (i1 < 0 || i2 < 0 || j1 < 0 || j2 < 0 38 | || i1 >= n || i2 >= n || j1 >= n || j2 >= n 39 | || !present[from] || !present[to]) { 40 | return; 41 | } 42 | add_edge(from, to, 1); 43 | } 44 | }; 45 | 46 | using namespace std; 47 | 48 | void solve() { 49 | int n; cin >> n; 50 | 51 | graph G(n * n); 52 | edge_adder adder(G); 53 | 54 | auto source = boost::add_vertex(G); 55 | auto target = boost::add_vertex(G); 56 | 57 | 58 | bool p; 59 | vector present(n * n, false); 60 | int count = 0; 61 | for (int i = 0; i < n; ++i) { 62 | for (int j = 0; j < n; ++j) { 63 | cin >> p; 64 | present[i * n + j] = p; 65 | 66 | if (!p) { 67 | continue; 68 | } 69 | 70 | ++count; 71 | 72 | int parity = (i + j) % 2; 73 | if (parity == 0) { 74 | adder.add_edge(source, i * n + j, 1); 75 | } 76 | else { 77 | adder.add_edge(i * n + j, target, 1); 78 | } 79 | } 80 | } 81 | 82 | // Build conflict graph 83 | for (int i = 0; i < n; ++i) { 84 | for (int j = 0; j < n; ++j) { 85 | int parity = (i + j) % 2; 86 | if (parity == 1) { 87 | continue; 88 | } 89 | adder.add_edge_if_exists(i, j, (i - 1), (j - 2), n, present); 90 | adder.add_edge_if_exists(i, j, (i - 1), (j + 2), n, present); 91 | adder.add_edge_if_exists(i, j, (i + 1), (j - 2), n, present); 92 | adder.add_edge_if_exists(i, j, (i + 1), (j + 2), n, present); 93 | adder.add_edge_if_exists(i, j, (i - 2), (j - 1), n, present); 94 | adder.add_edge_if_exists(i, j, (i - 2), (j + 1), n, present); 95 | adder.add_edge_if_exists(i, j, (i + 2), (j - 1), n, present); 96 | adder.add_edge_if_exists(i, j, (i + 2), (j + 1), n, present); 97 | } 98 | } 99 | 100 | 101 | long maxFlow = boost::push_relabel_max_flow(G, source, target); 102 | long maxMatching = maxFlow; 103 | long minVC = maxMatching; 104 | long maxIS = count - minVC; 105 | 106 | cout << maxIS << endl; 107 | } 108 | 109 | int main() { 110 | int t; cin >> t; 111 | for (int i = 0; i < t; ++i) { 112 | solve(); 113 | } 114 | } -------------------------------------------------------------------------------- /src/punch.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | // Value 8 | struct value { 9 | int cost; 10 | int numBeverages; 11 | bool usesBeverage; 12 | 13 | // "lexicographic" order with the following priorities: 14 | // 1. Cheapest 15 | // 2. Highest number of beverages 16 | // 3. Not needing to take the drink 17 | bool operator>(value v) { 18 | return cost < v.cost || 19 | (cost == v.cost && numBeverages > v.numBeverages) || 20 | (cost == v.cost && numBeverages == v.numBeverages && !usesBeverage && v.usesBeverage); 21 | } 22 | }; 23 | 24 | 25 | // Super similar to the knapsack problem 26 | // => Solve with DP 27 | void solve() 28 | { 29 | int n, k; 30 | cin >> n >> k; 31 | 32 | // Read costs and volumes 33 | vector c(n); 34 | vector v(n); 35 | for (int i = 0; i < n; ++i) { 36 | cin >> c[i] >> v[i]; 37 | } 38 | 39 | 40 | // Initialize DP 41 | // row i: all beverages up to i available 42 | // col j: at least j liters needed 43 | vector> dp(n, vector(k + 1)); 44 | for (int i = 1; i < n; ++i) { 45 | dp[i][0] = {0, 0, false}; 46 | } 47 | for (int j = 1; j <= k; ++j) { 48 | int cost = c[0] * int(ceil(1. * j / v[0])); 49 | dp[0][j] = {cost, 1, true}; 50 | } 51 | 52 | for (int i = 1; i < n; ++i) { 53 | for (int j = 1; j <= k; ++j) { 54 | // Value with i - 1 beverages 55 | value valueWithout = dp[i - 1][j]; 56 | valueWithout.usesBeverage = false; 57 | // Value with beverage i 58 | value valueWith = {c[i], 1, true}; 59 | // More than one bottle needed 60 | if (j > v[i]) { 61 | valueWith.cost += dp[i][j - v[i]].cost; 62 | valueWith.numBeverages = dp[i][j - v[i]].numBeverages; 63 | if (!dp[i][j - v[i]].usesBeverage) { 64 | valueWith.numBeverages += 1; 65 | } 66 | } 67 | 68 | // What is better? 69 | if (valueWithout > valueWith) { 70 | dp[i][j] = valueWithout; 71 | } 72 | else { 73 | dp[i][j] = valueWith; 74 | } 75 | } 76 | } 77 | 78 | // Print solution 79 | cout << dp[n - 1][k].cost << " " << dp[n - 1][k].numBeverages << endl; 80 | } 81 | 82 | int main() { 83 | ios_base::sync_with_stdio(false); 84 | int t; cin >> t; 85 | while (t--) { 86 | solve(); 87 | } 88 | return 0; 89 | } -------------------------------------------------------------------------------- /src/radiation.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | typedef CGAL::Gmpz IT; // input type 11 | typedef CGAL::Gmpz ET; // exact type for solver 12 | 13 | typedef CGAL::Quadratic_program Program; 14 | typedef CGAL::Quadratic_program_solution Solution; 15 | 16 | using namespace std; 17 | 18 | struct point { 19 | int x; 20 | int y; 21 | int z; 22 | }; 23 | 24 | vector coefficients(point &p, int d) { 25 | auto x = p.x; 26 | auto y = p.y; 27 | auto z = p.z; 28 | vector coeff; 29 | IT powerX = 1; 30 | for (int i = 0; i <= d; ++i) { 31 | IT powerXY = powerX; 32 | for (int j = 0; j <= d - i; ++j) { 33 | IT powerXYZ = powerXY; 34 | for (int k = 0; k <= d - i - j; ++k) { 35 | coeff.push_back(powerXYZ); 36 | powerXYZ *= z; 37 | } 38 | powerXY *= y; 39 | } 40 | powerX *= x; 41 | } 42 | return coeff; 43 | } 44 | 45 | bool isFeasible( vector &A, vector &B, int d) { 46 | Program lp = Program(CGAL::SMALLER, false, 0, false, 0); 47 | 48 | int h = A.size(); 49 | int t = B.size(); 50 | 51 | const int epsilon = 0; 52 | 53 | for (int i = 0; i < h; ++i) { 54 | auto coeff = coefficients(A[i], d); 55 | lp.set_a(epsilon, i, 1); 56 | for (int j = 0; j < coeff.size(); ++j) { 57 | lp.set_a(j + 1, i, coeff[j]); 58 | } 59 | } 60 | for (int i = 0; i < t; ++i) { 61 | auto coeff = coefficients(B[i], d); 62 | lp.set_a(epsilon, h + i, 1); 63 | for (int j = 0; j < coeff.size(); ++j) { 64 | lp.set_a(j + 1, h + i, -coeff[j]); 65 | } 66 | } 67 | 68 | // Epsilon needs to be greater or equal 0 69 | lp.set_l(epsilon, true, 0); 70 | 71 | // maximize epsilon <=> minimize -epsilon 72 | lp.set_c(epsilon, -1); 73 | 74 | CGAL::Quadratic_program_options options; 75 | options.set_pricing_strategy(CGAL::QP_BLAND); 76 | 77 | Solution s = CGAL::solve_linear_program(lp, ET(), options); 78 | 79 | if (s.is_infeasible()) { 80 | return false; 81 | } 82 | 83 | if (s.is_unbounded()) { 84 | return true; 85 | } 86 | 87 | return s.objective_value() < 0; 88 | } 89 | 90 | void solve() { 91 | int h; cin >> h; 92 | int t; cin >> t; 93 | 94 | vector A(h); 95 | vector B(t); 96 | 97 | int x, y, z; 98 | for (int i = 0; i < h; ++i) { 99 | cin >> x >> y >> z; 100 | A[i] = {x, y, z}; 101 | } 102 | for (int i = 0; i < t; ++i) { 103 | cin >> x >> y >> z; 104 | B[i] = {x, y, z}; 105 | } 106 | 107 | for (int d = 0; d <= 30; ++d) { 108 | if (isFeasible(A, B, d)) { 109 | cout << d << endl; 110 | return; 111 | } 112 | } 113 | cout << "Impossible!" << endl; 114 | } 115 | 116 | int main() { 117 | ios_base::sync_with_stdio(false); 118 | int t; cin >> t; 119 | for (int i = 0; i < t; ++i) { 120 | solve(); 121 | } 122 | return 0; 123 | } -------------------------------------------------------------------------------- /src/real_estate.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | // Graph Type with nested interior edge properties for Cost Flow Algorithms 9 | typedef boost::adjacency_list_traits traits; 10 | typedef boost::adjacency_list>>>> 15 | graph; // new! weightmap corresponds to costs 16 | typedef boost::graph_traits::edge_descriptor edge_desc; 17 | typedef boost::graph_traits::out_edge_iterator out_edge_it; // Iterator 18 | 19 | // Custom edge adder class 20 | class edge_adder 21 | { 22 | graph &G; 23 | 24 | public: 25 | explicit edge_adder(graph &G) : G(G) {} 26 | void add_edge(int from, int to, long capacity, long cost) 27 | { 28 | auto c_map = boost::get(boost::edge_capacity, G); 29 | auto r_map = boost::get(boost::edge_reverse, G); 30 | auto w_map = boost::get(boost::edge_weight, G); // new! 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; // reverse edge has no capacity! 35 | r_map[e] = rev_e; 36 | r_map[rev_e] = e; 37 | w_map[e] = cost; // new assign cost 38 | w_map[rev_e] = -cost; // new negative cost 39 | } 40 | }; 41 | 42 | using namespace std; 43 | 44 | void solve() 45 | { 46 | int buyers, sites, states; 47 | cin >> buyers >> sites >> states; 48 | 49 | graph G(states + sites + buyers); 50 | edge_adder adder(G); 51 | auto c_map = boost::get(boost::edge_capacity, G); 52 | auto r_map = boost::get(boost::edge_reverse, G); 53 | auto rc_map = boost::get(boost::edge_residual_capacity, G); 54 | 55 | auto source = boost::add_vertex(G); 56 | auto target = boost::add_vertex(G); 57 | 58 | int stateLimit; 59 | for (int state = 0; state < states; ++state) { 60 | cin >> stateLimit; 61 | adder.add_edge(source, state, stateLimit, 0); 62 | } 63 | 64 | int state; 65 | int offsetSites = states; 66 | for (int site = offsetSites; site < offsetSites + sites; ++site) { 67 | cin >> state; --state; // convert to 0 based 68 | adder.add_edge(state, site, 1, 0); 69 | } 70 | 71 | int bid; 72 | int maxBid = 100; 73 | int offsetBuyers = states + sites; 74 | for (int buyer = offsetBuyers; buyer < offsetBuyers + buyers; ++buyer) { 75 | for (int site = offsetSites; site < offsetSites + sites; ++site) { 76 | cin >> bid; 77 | adder.add_edge(site, buyer, 1, maxBid - bid); // Avoid negative costs 78 | } 79 | adder.add_edge(buyer, target, 1, 0); 80 | } 81 | 82 | boost::successive_shortest_path_nonnegative_weights(G, source, target); 83 | auto cost = boost::find_flow_cost(G); 84 | 85 | int flow = 0; 86 | out_edge_it e, eend; 87 | for (boost::tie(e, eend) = boost::out_edges(boost::vertex(source, G), G); e != eend; ++e) 88 | { 89 | flow += c_map[*e] - rc_map[*e]; 90 | } 91 | cost = maxBid * flow - cost; // Convert back to actual cost 92 | 93 | cout << flow << " " << cost << endl; 94 | } 95 | 96 | int main() 97 | { 98 | int t; cin >> t; 99 | for (int i = 0; i < t; ++i) { 100 | solve(); 101 | } 102 | return 0; 103 | } 104 | -------------------------------------------------------------------------------- /src/return_of_the_jedi.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | typedef boost::adjacency_list > weighted_graph; 12 | typedef boost::property_map::type weight_map; 13 | typedef boost::graph_traits::edge_descriptor edge_desc; 14 | typedef boost::graph_traits::vertex_descriptor vertex_desc; 15 | 16 | using namespace std; 17 | 18 | // Essentially, the tasks asks for the cost of the second best spanning tree. 19 | // Leia performs Prims MST algorithm. We need at least one edge different to the MST, 20 | // therefore, the best we can do is computing the second best spanning tree. 21 | void solve() { 22 | // Tatooine is not needed for anything 23 | int n, tatooine; 24 | cin >> n >> tatooine; 25 | 26 | // Compute a MST (with any algorithm) 27 | weighted_graph G(n); 28 | 29 | int cost; 30 | vector> costs(n, vector(n)); 31 | for (int j = 0; j < n - 1; ++j) { 32 | for (int k = 0; k < n - j - 1; ++k) { 33 | int u = j; 34 | int v = j + k + 1; 35 | cin >> cost; 36 | costs[u][v] = cost; 37 | costs[v][u] = cost; 38 | boost::add_edge(u, v, cost, G); 39 | } 40 | } 41 | 42 | // Use Kurskal (we could also use Prim...does not make any difference) 43 | std::vector mst; 44 | boost::kruskal_minimum_spanning_tree(G, std::back_inserter(mst)); 45 | 46 | // Extract neighbors from MST and compute MST Value 47 | int mstValue = 0; 48 | vector> neighbors(n); 49 | vector> isMstEdge(n, vector(n, false)); 50 | for (auto edge : mst) { 51 | int u = boost::source(edge, G); 52 | int v = boost::target(edge, G); 53 | mstValue += costs[u][v]; 54 | neighbors[u].push_back(v); 55 | neighbors[v].push_back(u); 56 | isMstEdge[u][v] = true; 57 | isMstEdge[v][u] = true; 58 | } 59 | 60 | // Compute the most expensive edge for every u-v path in the MST 61 | vector> uvMaxEdge(n, vector(n, 0)); 62 | 63 | for (int u = 0; u < n; ++u) { 64 | vector stack; 65 | stack.push_back(u); 66 | vector visited(n, false); 67 | visited[u] = true; 68 | 69 | while (!stack.empty()) { 70 | int v = *stack.rbegin(); 71 | stack.pop_back(); 72 | 73 | for (auto w : neighbors[v]) { 74 | if (!visited[w]) { 75 | visited[w] = true; 76 | uvMaxEdge[u][w] = max(costs[v][w], uvMaxEdge[u][v]); 77 | stack.push_back(w); 78 | } 79 | } 80 | } 81 | } 82 | 83 | // For all edges e = {u, v}, that are not in the MST, we will try adding e to the MST. 84 | // This will introduce a cycle. We remove the most expensive edge of the cycle that is 85 | // part of the MST. For this we can simply query the most expensive edge from u to v in the MST 86 | // and remove it. The cost of the MST changes by delta = cost[u][v] - cost[most expensive edge]. 87 | // We simply find the best delta. 88 | int minVal = numeric_limits::max(); 89 | for (int u = 0; u < n; ++u) { 90 | for (int v = u + 1; v < n; ++v) { 91 | if (!isMstEdge[u][v]) { 92 | int val = costs[u][v] - uvMaxEdge[u][v]; 93 | minVal = min(val, minVal); 94 | } 95 | } 96 | } 97 | 98 | cout << mstValue + minVal << endl; 99 | } 100 | 101 | 102 | int main() { 103 | ios_base::sync_with_stdio(false); 104 | int t; cin >> t; 105 | while(t--) { 106 | solve(); 107 | } 108 | } -------------------------------------------------------------------------------- /src/russia_official_solution.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | typedef std::vector VI; 5 | typedef std::vector VVI; 6 | // global upper bound on winnings: <= 500 coins of value <= 2^{10} 7 | // (fits into a 32-bit int) 8 | const int INF = 500 * 1024 + 1; 9 | // n = #coins, m = #players, 10 | // x[i] is the value of the i-th coin, and 11 | // dp[i][j], where i <= j is the maximum possible winnings 12 | // of the first player given that the game starts with coins 13 | // x[i], x[i+1], ..., x[j-1]. 14 | // This recursive function computes dp[i][j], that is, the maximum possible 15 | // winnings of the first player given that the game starts with coins 16 | // x[i], x[i+1], ..., x[j-1]. 17 | int max_winnings(int i, int j, int n, int m, const VI& x, VVI& dp) { 18 | // If (i, j) is not a valid interval, return 0. 19 | if (j < i) return 0; 20 | // If there are fewer than 1 coins available, the first 21 | // player will not get a coin, so his/her winnings are 0. 22 | if (j - i < 1) return dp[i][j] = 0; 23 | // If we have already computed the value for this state, 24 | // we don’t compute it again. 25 | if (dp[i][j] != -1) return dp[i][j]; 26 | // The following implements the recurrent formula from above. 27 | int winnings_kth_left = INF, winnings_kth_right = INF; 28 | for (int l = 0; l < m; ++l) { 29 | winnings_kth_left = std::min( 30 | winnings_kth_left, 31 | max_winnings(i + l + 1, j - (m - l - 1), n, m, x, dp)); 32 | winnings_kth_right = std::min( 33 | winnings_kth_right, 34 | max_winnings(i + l, j - (m - l), n, m, x, dp)); 35 | } 36 | dp[i][j] = std::max(x[i] + winnings_kth_left, x[j-1] + winnings_kth_right); 37 | return dp[i][j]; 38 | } 39 | 40 | int main() { 41 | std::ios_base::sync_with_stdio(false); 42 | int t; 43 | // Read in the number of test cases. 44 | for (std::cin >> t; t > 0; --t) { 45 | int n, m, k; 46 | std::cin >> n >> m >> k; 47 | // Read in all the values of the coins. 48 | VI x; 49 | x.reserve(n); 50 | for (int i = 0; i < n; ++i) { 51 | int v; 52 | std::cin >> v; 53 | x.push_back(v); 54 | } 55 | // Make sure our dp array is initialized to -1, which stands for 56 | // "not computed yet". 57 | VVI dp(n+1, VI(n+1, -1)); 58 | // Consider all options for the behaviour of the first ‘k‘ players. 59 | // Any number of them (0 through k) could take the leftmost coins. 60 | // We take the minimum winnings for the k-th player out of all these. 61 | int maximal_winnings = INF; 62 | for (int i = 0; i <= k; ++i) 63 | maximal_winnings = std::min( 64 | maximal_winnings, 65 | max_winnings(i, n - (k - i), n, m, x, dp)); 66 | std::cout << maximal_winnings << "\n"; 67 | } 68 | } -------------------------------------------------------------------------------- /src/san_francisco.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | struct edge { 8 | int v; 9 | int p; 10 | }; 11 | 12 | void solve() { 13 | int n; cin >> n; 14 | int m; cin >> m; 15 | long x; cin >> x; 16 | int k; cin >> k; 17 | 18 | vector> neighbors(n, vector()); 19 | 20 | int u, v, p; 21 | for (int i = 0; i < m; ++i) { 22 | cin >> u; 23 | cin >> v; 24 | cin >> p; 25 | neighbors[u].push_back(edge({v, p})); 26 | } 27 | 28 | for (int u = 0; u < n; ++u) { 29 | if (neighbors[u].size() == 0) { 30 | for (unsigned int j = 0; j < neighbors[0].size(); ++j) { 31 | neighbors[u].push_back(neighbors[0][j]); 32 | } 33 | } 34 | } 35 | 36 | vector dp(n, -1); 37 | dp[0] = 0; 38 | 39 | int kMin = -1; 40 | for (int i = 0; i < k; ++i) { 41 | vector dpNew(n, -1); 42 | 43 | for (int u = 0; u < n; ++u) { 44 | if (dp[u] != -1) { 45 | for (unsigned int j = 0; j < neighbors[u].size(); ++j) { 46 | auto e = neighbors[u][j]; 47 | dpNew[e.v] = max(dpNew[e.v], dp[u] + e.p); 48 | if (dpNew[e.v] >= x && kMin == -1) { 49 | kMin = i; 50 | break; 51 | } 52 | } 53 | } 54 | } 55 | 56 | dp = dpNew; 57 | } 58 | if (kMin == -1) { 59 | cout << "Impossible" << endl; 60 | } else { 61 | cout << kMin + 1 << endl; 62 | } 63 | } 64 | 65 | int main() { 66 | ios_base::sync_with_stdio(false); 67 | int t; cin >> t; 68 | for (int i = 0; i < t; ++i) { 69 | solve(); 70 | } 71 | } -------------------------------------------------------------------------------- /src/search_snippets.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | struct wordIndex { 8 | int index; 9 | int word; 10 | 11 | bool operator<(const wordIndex &rhs) { 12 | return index < rhs.index; 13 | } 14 | }; 15 | 16 | 17 | void solve() { 18 | int n; 19 | cin >> n; 20 | vector m; 21 | vector> p(n, vector()); 22 | vector wordIndices; 23 | int in; 24 | int lastWordIndex = 0; 25 | for (int i = 0; i < n; ++i) { 26 | cin >> in; 27 | m.push_back(in); 28 | } 29 | for (int i = 0; i < n; ++i) { 30 | for (int j = 0; j < m[i]; ++j) { 31 | cin >> in; 32 | p[i].push_back(in); 33 | wordIndices.push_back(wordIndex{p[i][j], i}); 34 | } 35 | //sort(p[i].begin(), p[i].end()); 36 | lastWordIndex = max(lastWordIndex, p[i][0]); 37 | } 38 | sort(wordIndices.begin(), wordIndices.end()); 39 | 40 | int i = 0; 41 | int j = 0; 42 | vector pi(n, 0); 43 | 44 | // Move j to first position, where all words are covered 45 | while (wordIndices[j].index != lastWordIndex) { 46 | ++j; 47 | } 48 | 49 | int w = wordIndices.size(); 50 | int minLength = 1073741826; 51 | 52 | while (i < w && j < w) { 53 | 54 | wordIndex a = wordIndices[i]; 55 | wordIndex b = wordIndices[j]; 56 | int length = b.index - a.index + 1; 57 | minLength = min(minLength, length); 58 | 59 | // Check if moving i is allowed 60 | bool moveI = true; 61 | int word = a.word; 62 | if (pi[word] + 1 >= m[word]) { 63 | // Already last occurrence of word 64 | break; 65 | } else { 66 | int nextWordIndex = p[word][pi[word] + 1]; 67 | moveI = a.index < nextWordIndex && nextWordIndex <= b.index; 68 | } 69 | 70 | 71 | if (moveI) { 72 | ++i; 73 | pi[word] += 1; 74 | } else { 75 | ++j; 76 | } 77 | 78 | 79 | } 80 | 81 | 82 | cout << minLength << endl; 83 | } 84 | 85 | int main() { 86 | int t; 87 | cin >> t; 88 | for (int i = 0; i < t; ++i) { 89 | solve(); 90 | } 91 | } -------------------------------------------------------------------------------- /src/secret_service.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | // For dijkstra 10 | typedef boost::adjacency_list > weighted_graph; 12 | typedef boost::property_map::type weight_map; 13 | 14 | 15 | // For max flow 16 | typedef boost::adjacency_list_traits traits; 17 | typedef boost::adjacency_list>>> graph; 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; // reverse edge has no capacity! 35 | r_map[e] = rev_e; 36 | r_map[rev_e] = e; 37 | } 38 | }; 39 | 40 | using namespace std; 41 | 42 | // Compute shortest distances 43 | void dijkstra(const weighted_graph &G, int s, vector& dist_map) { 44 | boost::dijkstra_shortest_paths(G, s, 45 | boost::distance_map(boost::make_iterator_property_map( 46 | dist_map.begin(), boost::get(boost::vertex_index, G)))); 47 | } 48 | 49 | // Is it possible for all agents to seek shelter for a given tMax? 50 | bool isFeasible(vector>& timeToShelter, int capacity, int timeToEnter, int tMax) { 51 | int a = timeToShelter.size(); 52 | int s = timeToShelter[0].size(); 53 | 54 | graph G(a + capacity * s + 2); 55 | edge_adder adder(G); 56 | int source = a + capacity * s; 57 | int target = source + 1; 58 | 59 | for (int i = 0; i < a; ++i) { 60 | adder.add_edge(source, i, 1); 61 | } 62 | 63 | for (int j = 0; j < s; ++j) { 64 | for (int c = 1; c <= capacity; ++c) { 65 | adder.add_edge(a + (c - 1) * s + j, target, 1); 66 | } 67 | } 68 | 69 | 70 | for (int i = 0; i < a; ++i) { 71 | for (int j = 0; j < s; ++j) { 72 | for (int c = 1; c <= capacity; ++c) { 73 | if (timeToShelter[i][j] <= tMax - c * timeToEnter) { 74 | adder.add_edge(i, a + (c - 1) * s + j, 1); 75 | } 76 | } 77 | } 78 | } 79 | 80 | long flow = boost::push_relabel_max_flow(G, source, target); 81 | return flow == a; 82 | } 83 | 84 | // Use binary search to find the smallest t such that (isFeasible(t) == True) 85 | void solve() { 86 | 87 | int n, m, a, s, c, d; 88 | cin >> n >> m >> a >> s >> c >> d; 89 | 90 | // Read skiing area 91 | weighted_graph G(n); 92 | char w; 93 | int x, y, z; 94 | for (int i = 0; i < m; ++i) { 95 | cin >> w >> x >> y >> z; 96 | 97 | boost::add_edge(x, y, z, G); 98 | if (w == 'L') { 99 | boost::add_edge(y, x, z, G); 100 | } 101 | } 102 | 103 | // Read agent positions 104 | vector agents(a); 105 | for (int i = 0; i < a; ++i) { 106 | cin >> agents[i]; 107 | } 108 | 109 | // Read shelter positions 110 | vector shelters(s); 111 | for (int j = 0; j < s; ++j) { 112 | cin >> shelters[j]; 113 | } 114 | 115 | vector> distToShelter(a, vector(s)); 116 | for (int i = 0; i < a; ++i) { 117 | vector dist_map(n); 118 | dijkstra(G, agents[i], dist_map); 119 | for (int j = 0; j < s; ++j) { 120 | distToShelter[i][j] = dist_map[shelters[j]]; 121 | } 122 | } 123 | 124 | int low = 1; 125 | int high = numeric_limits::max() - 1; 126 | 127 | while (low != high) { 128 | int t = low + (high - low) / 2; 129 | if (isFeasible(distToShelter, c, d, t)) { 130 | high = t; 131 | } 132 | else { 133 | low = t + 1; 134 | } 135 | } 136 | 137 | cout << low << endl; 138 | 139 | } 140 | 141 | int main() 142 | { 143 | ios_base::sync_with_stdio(false); 144 | int t; cin >> t; 145 | while (t--) { 146 | solve(); 147 | } 148 | return 0; 149 | } 150 | -------------------------------------------------------------------------------- /src/shopping_trip.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | // Graph Type with nested interior edge properties for flow algorithms 8 | typedef boost::adjacency_list_traits traits; 9 | typedef boost::adjacency_list>>> graph; 13 | 14 | typedef traits::vertex_descriptor vertex_desc; 15 | typedef traits::edge_descriptor edge_desc; 16 | 17 | class edge_adder { 18 | graph &G; 19 | 20 | public: 21 | explicit edge_adder(graph &G) : G(G) {} 22 | 23 | void add_edge(int from, int to, long capacity) { 24 | auto c_map = boost::get(boost::edge_capacity, G); 25 | auto r_map = boost::get(boost::edge_reverse, G); 26 | const auto e = boost::add_edge(from, to, G).first; 27 | const auto rev_e = boost::add_edge(to, from, G).first; 28 | c_map[e] = capacity; 29 | c_map[rev_e] = 0; // reverse edge has no capacity! 30 | r_map[e] = rev_e; 31 | r_map[rev_e] = e; 32 | } 33 | }; 34 | 35 | 36 | using namespace std; 37 | 38 | void solve() { 39 | int n; cin >> n; 40 | int m; cin >> m; 41 | int s; cin >> s; 42 | 43 | vector stores(s); 44 | for (int i = 0; i < s; ++i) { 45 | cin >> stores[i]; 46 | } 47 | 48 | graph G(n); 49 | edge_adder adder(G); 50 | 51 | int u, v; 52 | for (int i = 0; i < m; ++i) { 53 | cin >> u; 54 | cin >> v; 55 | adder.add_edge(u, v, 1); 56 | adder.add_edge(v, u, 1); 57 | } 58 | 59 | int source = 0; 60 | vertex_desc target = boost::add_vertex(G); 61 | 62 | for (int i = 0; i < s; ++i) { 63 | adder.add_edge(stores[i], target, 1); 64 | } 65 | 66 | long flow = boost::push_relabel_max_flow(G, source, target); 67 | if (flow == s) { 68 | cout << "yes" << endl; 69 | } 70 | else { 71 | cout << "no" << endl; 72 | } 73 | } 74 | 75 | int main() { 76 | ios_base::sync_with_stdio(false); 77 | int t; cin >> t; 78 | for (int i = 0; i < t; ++i) { 79 | solve(); 80 | } 81 | } -------------------------------------------------------------------------------- /src/sith.cpp: -------------------------------------------------------------------------------- 1 | ///1 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 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 | typedef std::pair IPoint; 22 | typedef std::tuple Edge; 23 | typedef std::vector EdgeV; 24 | typedef Tds::Vertex_handle Vh; 25 | 26 | typedef boost::adjacency_list graph; 27 | typedef boost::graph_traits::vertex_descriptor vertex_desc; 28 | typedef boost::graph_traits::edge_iterator edge_it; 29 | 30 | using namespace std; 31 | 32 | // Strategy: 33 | // - Binary search for the best k 34 | // - For a given k, construct a Graph that contains only points p_k...p_{n-1} 35 | // - Find the largest connected component 36 | void solve() { 37 | int n; 38 | long r; 39 | cin >> n >> r; 40 | long r2 = r * r; 41 | 42 | vector points; 43 | points.reserve(n); 44 | int x, y; 45 | for (int i = 0; i < n; ++i) { 46 | cin >> x >> y; 47 | points.emplace_back(K::Point_2(x, y), i); 48 | } 49 | 50 | 51 | // Start binary search 52 | int a = 1; 53 | int b = n; 54 | while (a < b - 1) { 55 | 56 | int empireSize = (a + b) / 2; 57 | 58 | // Use delaunay to quickly construct graph of points outside the empire 59 | Delaunay dt; 60 | dt.insert(points.begin() + empireSize, points.end()); 61 | 62 | graph G(n - empireSize); 63 | for (auto e = dt.finite_edges_begin(); e != dt.finite_edges_end(); ++e) { 64 | int u = e->first->vertex((e->second+1)%3)->info(); 65 | int v = e->first->vertex((e->second+2)%3)->info(); 66 | if (dt.segment(e).squared_length() <= r2) { 67 | boost::add_edge(u - empireSize, v - empireSize, G); 68 | } 69 | } 70 | 71 | // Compute largest connected component 72 | std::vector component_map(n); 73 | int ncc = boost::connected_components(G, boost::make_iterator_property_map(component_map.begin(), boost::get(boost::vertex_index, G))); 74 | 75 | int largestComponent = 0; 76 | vector componentSize(ncc, 0); 77 | for (int i = 0; i < n - empireSize; ++i) { 78 | int c = component_map[i]; 79 | componentSize[c]++; 80 | largestComponent = max(largestComponent, int(componentSize[c])); 81 | } 82 | 83 | // Continue binary search 84 | if (empireSize <= largestComponent) { 85 | // Invalid solution, the empire must be at least as large as the rebel alliance (both expand equally fast) 86 | // => Expand empire 87 | a = empireSize; 88 | } 89 | else { 90 | b = empireSize; 91 | } 92 | } 93 | cout << a << endl; 94 | } 95 | 96 | int main() { 97 | ios_base::sync_with_stdio(false); 98 | int t; cin >> t; 99 | while (t--) { 100 | solve(); 101 | } 102 | return 0; 103 | } 104 | 105 | -------------------------------------------------------------------------------- /src/surveillance.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | // Graph Type with nested interior edge properties for flow algorithms 8 | typedef boost::adjacency_list_traits traits; 9 | typedef boost::adjacency_list>>> graph; 13 | 14 | typedef traits::vertex_descriptor vertex_desc; 15 | typedef traits::edge_descriptor edge_desc; 16 | 17 | class edge_adder { 18 | graph &G; 19 | 20 | public: 21 | explicit edge_adder(graph &G) : G(G) {} 22 | 23 | void add_edge(int from, int to, long capacity) { 24 | auto c_map = boost::get(boost::edge_capacity, G); 25 | auto r_map = boost::get(boost::edge_reverse, G); 26 | const auto e = boost::add_edge(from, to, G).first; 27 | const auto rev_e = boost::add_edge(to, from, G).first; 28 | c_map[e] = capacity; 29 | c_map[rev_e] = 0; // reverse edge has no capacity! 30 | r_map[e] = rev_e; 31 | r_map[rev_e] = e; 32 | } 33 | }; 34 | 35 | 36 | using namespace std; 37 | 38 | void solve() { 39 | int n; cin >> n; 40 | int m; cin >> m; 41 | int k; cin >> k; 42 | int l; cin >> l; 43 | 44 | graph G(2 * n); 45 | edge_adder adder(G); 46 | 47 | vertex_desc source = boost::add_vertex(G); 48 | vertex_desc target = boost::add_vertex(G); 49 | 50 | int x; 51 | for (int i = 0; i < k; ++i) { 52 | cin >> x; 53 | adder.add_edge(source, x, 1); 54 | adder.add_edge(n + x, target, 1); 55 | } 56 | 57 | for (int i = 0; i < l; ++i) { 58 | cin >> x; 59 | adder.add_edge(x, n + x, 1); 60 | } 61 | 62 | 63 | int u, v; 64 | for (int i = 0; i < m; ++i) { 65 | cin >> u; 66 | cin >> v; 67 | adder.add_edge(u, v, k); 68 | adder.add_edge(n + u, n + v, 1); 69 | } 70 | 71 | long flow = boost::push_relabel_max_flow(G, source, target); 72 | cout << flow << endl; 73 | } 74 | 75 | int main() { 76 | ios_base::sync_with_stdio(false); 77 | int t; cin >> t; 78 | for (int i = 0; i < t; ++i) { 79 | solve(); 80 | } 81 | } -------------------------------------------------------------------------------- /src/switzerland.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | typedef boost::adjacency_list_traits traits; 10 | typedef boost::adjacency_list > > > graph; 14 | typedef boost::graph_traits::edge_descriptor edge_desc; 15 | typedef boost::graph_traits::out_edge_iterator out_edge_it; 16 | 17 | 18 | class edge_adder { 19 | graph &G; 20 | 21 | public: 22 | explicit edge_adder(graph &G) : G(G) {} 23 | 24 | void add_edge(int from, int to, long capacity) { 25 | auto c_map = boost::get(boost::edge_capacity, G); 26 | auto r_map = boost::get(boost::edge_reverse, G); 27 | const edge_desc e = boost::add_edge(from, to, G).first; 28 | const edge_desc rev_e = boost::add_edge(to, from, G).first; 29 | c_map[e] = capacity; 30 | c_map[rev_e] = 0; // reverse edge has no capacity! 31 | r_map[e] = rev_e; 32 | r_map[rev_e] = e; 33 | } 34 | }; 35 | 36 | using namespace std; 37 | 38 | // Modeling it as a flow problem. 39 | // The source connects to all vertices with a positive balance, all other vertices connect to the sink. 40 | // Since an unions total value needs to be strictly greater than zero, we know there needs to be at 41 | // least one province that does not need its full balance to support it. I no such province exists, 42 | // there can not be an union. If there is a province that does not need its full balance, the flow is 43 | // less than the sum of positive balances 44 | void solve() { 45 | int n, m; 46 | cin >> n >> m; 47 | 48 | // Set up the graph 49 | graph G(n); 50 | edge_adder adder(G); 51 | auto rc_map = boost::get(boost::edge_residual_capacity, G); 52 | 53 | auto source = boost::add_vertex(G); 54 | auto target = boost::add_vertex(G); 55 | 56 | // Connect all provinces to source/target depending on balance 57 | int sumPositive = 0; 58 | int b; 59 | for (int i = 0; i < n; ++i) { 60 | cin >> b; 61 | if (b > 0) { 62 | sumPositive += b; 63 | adder.add_edge(source, i, b); 64 | } 65 | else { 66 | adder.add_edge(i, target, -b); 67 | } 68 | } 69 | 70 | // Connect provinces 71 | int u, v, d; 72 | for (int i = 0; i < m; ++i) { 73 | cin >> u >> v >> d; 74 | adder.add_edge(u, v, d); 75 | } 76 | 77 | 78 | // Compute flow & output 79 | int flow = boost::push_relabel_max_flow(G, source, target); 80 | cout << (flow < sumPositive ? "yes" : "no") << endl; 81 | } 82 | 83 | int main() { 84 | ios_base::sync_with_stdio(false); 85 | int t; cin >> t; 86 | for (int i = 0; i < t; ++i) { 87 | solve(); 88 | } 89 | return 0; 90 | } -------------------------------------------------------------------------------- /src/the_great_game.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | 9 | int solve() { 10 | int n; std::cin >> n; 11 | int m; std::cin >> m; 12 | int r; std::cin >> r; r = r - 1; 13 | int b; std::cin >> b; b = b - 1; 14 | vector> neighbors(n, vector()); 15 | int u, v; 16 | for (int i = 0; i < m; ++i) { 17 | cin >> u; 18 | cin >> v; 19 | // u,v are in range [1...n], transform to [0...n-1] 20 | neighbors[u - 1].push_back(v - 1); 21 | } 22 | 23 | vector minSteps(n, numeric_limits::max()); 24 | vector maxSteps(n, -1); 25 | 26 | minSteps[n - 1] = 0; 27 | maxSteps[n - 1] = 0; 28 | 29 | for (int u = n - 2; u >= 0; --u) { 30 | for (int v : neighbors[u]) { 31 | minSteps[u] = min(maxSteps[v] + 1, minSteps[u]); 32 | maxSteps[u] = max(minSteps[v] + 1, maxSteps[u]); 33 | } 34 | } 35 | 36 | if (minSteps[r] < minSteps[b]) { 37 | return 0; 38 | } 39 | 40 | if (minSteps[r] > minSteps[b]) { 41 | return 1; 42 | } 43 | 44 | if (minSteps[r] % 2 == 1) { 45 | return 0; 46 | } 47 | 48 | return 1; 49 | } 50 | 51 | int main() { 52 | 53 | ios_base::sync_with_stdio(false); 54 | 55 | int t; std::cin >> t; 56 | for (int i = 0; i < t; ++i) { 57 | int solution = solve(); 58 | std::cout << solution << std::endl; 59 | } 60 | } -------------------------------------------------------------------------------- /src/tiles.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | // Graph Type with nested interior edge properties for flow algorithms 8 | typedef boost::adjacency_list_traits traits; 9 | typedef boost::adjacency_list>>> graph; 13 | 14 | typedef traits::vertex_descriptor vertex_desc; 15 | typedef traits::edge_descriptor edge_desc; 16 | 17 | class edge_adder { 18 | graph &G; 19 | 20 | public: 21 | explicit edge_adder(graph &G) : G(G) {} 22 | 23 | void add_edge(int from, int to, long capacity) { 24 | auto c_map = boost::get(boost::edge_capacity, G); 25 | auto r_map = boost::get(boost::edge_reverse, G); 26 | const auto e = boost::add_edge(from, to, G).first; 27 | const auto rev_e = boost::add_edge(to, from, G).first; 28 | c_map[e] = capacity; 29 | c_map[rev_e] = 0; // reverse edge has no capacity! 30 | r_map[e] = rev_e; 31 | r_map[rev_e] = e; 32 | } 33 | }; 34 | 35 | 36 | using namespace std; 37 | 38 | void solve() { 39 | int cols; cin >> cols; 40 | int rows; cin >> rows; 41 | 42 | graph G; 43 | edge_adder adder(G); 44 | 45 | int targetFlow = 0; 46 | vertex_desc source = boost::add_vertex(G); 47 | vertex_desc target = boost::add_vertex(G); 48 | 49 | vector> in(rows, vector(cols)); 50 | vector> out(rows, vector(cols)); 51 | for (int row = 0; row < rows; ++row) { 52 | for (int col = 0; col < cols; ++col) { 53 | in[row][col] = boost::add_vertex(G); 54 | out[row][col] = boost::add_vertex(G); 55 | } 56 | } 57 | for (int row = 0; row < rows; ++row) { 58 | for (int col = 0; col < cols; ++col) { 59 | char c; cin >> c; 60 | bool blocked = (c == 'x'); 61 | if (blocked) { 62 | continue; 63 | } 64 | bool even = (row + col) % 2 == 0; 65 | if (even) { 66 | adder.add_edge(source, in[row][col], 1); 67 | 68 | if (row > 0) 69 | adder.add_edge(in[row][col], out[row - 1][col], 1); 70 | if (row < rows - 1) 71 | adder.add_edge(in[row][col], out[row + 1][col], 1); 72 | if (col > 0) 73 | adder.add_edge(in[row][col], out[row][col - 1], 1); 74 | if (col < cols - 1) 75 | adder.add_edge(in[row][col], out[row][col + 1], 1); 76 | } 77 | else { 78 | adder.add_edge(out[row][col], target, 1); 79 | } 80 | ++targetFlow; 81 | } 82 | } 83 | if (targetFlow % 2 != 0) { 84 | cout << "no" << endl; 85 | return; 86 | } 87 | targetFlow /= 2; 88 | 89 | long flow = boost::push_relabel_max_flow(G, source, target); 90 | cout << ((flow == targetFlow) ? "yes" : "no") << endl; 91 | } 92 | 93 | int main() { 94 | ios_base::sync_with_stdio(false); 95 | int t; cin >> t; 96 | for (int i = 0; i < t; ++i) { 97 | solve(); 98 | } 99 | } -------------------------------------------------------------------------------- /src/tracking.cpp: -------------------------------------------------------------------------------- 1 | // STL includes 2 | #include 3 | #include 4 | 5 | // BGL includes 6 | #include 7 | #include 8 | 9 | typedef boost::adjacency_list > weighted_graph; 11 | typedef boost::property_map::type weight_map; 12 | typedef boost::graph_traits::edge_descriptor edge_desc; 13 | typedef boost::graph_traits::vertex_descriptor vertex_desc; 14 | 15 | int dijkstra_dist(const weighted_graph &G, int s, int t) { 16 | int n = boost::num_vertices(G); 17 | std::vector dist_map(n); 18 | 19 | boost::dijkstra_shortest_paths(G, s, 20 | boost::distance_map(boost::make_iterator_property_map( 21 | dist_map.begin(), boost::get(boost::vertex_index, G)))); 22 | 23 | return dist_map[t]; 24 | } 25 | 26 | int index(int v, int k, int n) { 27 | return k * n + v; 28 | } 29 | 30 | void solve() 31 | { 32 | int n; std::cin >> n; 33 | int m; std::cin >> m; 34 | int k; std::cin >> k; 35 | int x; std::cin >> x; 36 | int y; std::cin >> y; 37 | 38 | 39 | weighted_graph G; 40 | 41 | int a, b, c, d; 42 | for (int i = 0; i < m; ++i) { 43 | std::cin >> a; 44 | std::cin >> b; 45 | std::cin >> c; 46 | std::cin >> d; 47 | 48 | for (int j = 1; j <= k; ++j) { 49 | boost::add_edge(a + j * n, b + (j - d) * n, c, G); 50 | boost::add_edge(b + j * n, a + (j - d) * n, c, G); 51 | } 52 | boost::add_edge(a, b, c, G); 53 | boost::add_edge(b, a, c, G); 54 | } 55 | 56 | std::cout << dijkstra_dist(G, x + k * n, y) << std::endl; 57 | } 58 | 59 | int main() { 60 | std::ios_base::sync_with_stdio(false); 61 | int t; std::cin >> t; 62 | for (int i = 0; i < t; ++i) { 63 | solve(); 64 | } 65 | } -------------------------------------------------------------------------------- /src/worldcup.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | typedef int IT; 14 | typedef CGAL::Gmpz ET; 15 | 16 | typedef CGAL::Quadratic_program Program; 17 | typedef CGAL::Quadratic_program_solution Solution; 18 | 19 | typedef CGAL::Exact_predicates_inexact_constructions_kernel K; 20 | typedef CGAL::Delaunay_triangulation_2 DT; 21 | 22 | using namespace std; 23 | 24 | // Annoying function for output 25 | double floor_to_double(const CGAL::Quotient& x) { 26 | double a = floor(CGAL::to_double(x)); 27 | while (a > x) a -= 1; 28 | while (a + 1 <= x) a += 1; 29 | return a; 30 | } 31 | 32 | void solve() { 33 | int n, m, c; 34 | cin >> n >> m >> c; 35 | 36 | // Read warehouses 37 | long x, y; 38 | vector supply(n); 39 | vector alcoholPercentage(n); 40 | vector warehouses(n); 41 | for (int i = 0; i < n; ++i) { 42 | cin >> x >> y >> supply[i] >> alcoholPercentage[i]; 43 | warehouses[i] = K::Point_2(x, y); 44 | } 45 | 46 | // Read stadiums 47 | vector demand(m); 48 | vector upperAlcoholLimit(m); 49 | vector stadiums(m); 50 | for (int j = 0; j < m; ++j) { 51 | cin >> x >> y >> demand[j] >> upperAlcoholLimit[j]; 52 | stadiums[j] = K::Point_2(x, y); 53 | } 54 | 55 | // Read revenues 56 | vector> revenue(n, vector(m)); 57 | for (int i = 0; i < n; ++i) { 58 | for (int j = 0; j < m; ++j) { 59 | cin >> revenue[i][j]; 60 | } 61 | } 62 | 63 | 64 | // We have many contour lines, but only a few are relevant (i.e. at most 100). We only store those. 65 | // If a contour does not contain any relevant point (warehouse or stadium), it is irrelevant. 66 | // We find the closest relevant (with a DT) point and use the radius to check if it is inside the contour. 67 | DT dt; 68 | dt.insert(warehouses.begin(), warehouses.end()); 69 | dt.insert(stadiums.begin(), stadiums.end()); 70 | 71 | // Read contour lines 72 | long r; 73 | vector r2; 74 | vector contours; 75 | for (int i = 0; i < c; ++i) { 76 | cin >> x >> y >> r; 77 | K::Point_2 p(x, y); 78 | // Does it contain any stadium / warehouse? 79 | auto nearest = dt.nearest_vertex(p); 80 | if (CGAL::squared_distance(nearest->point(), p) <= K::FT(r * r)) { 81 | r2.emplace_back(r * r); 82 | contours.push_back(p); 83 | } 84 | } 85 | 86 | // For every contour, find contained warehouse and stadium. Save it. 87 | vector> warehouseContours(n); 88 | vector> stadiumContours(m); 89 | for (int k = 0; k < contours.size(); ++k) { 90 | for (int i = 0; i < n; ++i) { 91 | if (CGAL::squared_distance(warehouses[i], contours[k]) <= r2[k]) { 92 | warehouseContours[i].insert(k); 93 | } 94 | } 95 | for (int j = 0; j < m; ++j) { 96 | if (CGAL::squared_distance(stadiums[j], contours[k]) <= r2[k]) { 97 | stadiumContours[j].insert(k); 98 | } 99 | } 100 | } 101 | 102 | // Calculate profit based on revenue and on how many contour line are traversed. 103 | // The profit is multiplied by 100 to avoid rational numbers. 104 | vector> profit(n, vector(m));; 105 | for (int i = 0; i < n; ++i) { 106 | for (int j = 0; j < m; ++j) { 107 | auto &a = warehouseContours[i]; 108 | auto &b = stadiumContours[j]; 109 | vector its; 110 | set_intersection(a.begin(), a.end(), b.begin(), b.end(), back_inserter(its)); 111 | int t = a.size() + b.size() - 2 * its.size(); 112 | profit[i][j] = revenue[i][j] * 100 - t; 113 | } 114 | } 115 | 116 | // Solve it with linear programming. 117 | // There is one variable for every warehouse-stadium pair. 118 | // A variable x_ij describes the amount of beer (liters) transported from warehouse i to stadium j. 119 | // All variables must obviously be positive. 120 | Program lp = Program(CGAL::SMALLER, true, 0, false, 0); 121 | 122 | // Warehouse constraints 123 | for (int i = 0; i < n; ++i) { 124 | // sum x_ij <= supply[i] 125 | lp.set_b(i, supply[i]); 126 | for (int j = 0; j < m; ++j) { 127 | int x_ij = i * m + j; 128 | lp.set_a(x_ij, i, 1); 129 | } 130 | } 131 | 132 | // Stadium constraints 133 | for (int j = 0; j < m; ++j) { 134 | // (1) sum x_ij <= demand 135 | // (2) sum x_ij >= demand <=> sum -x_ij <= -demand 136 | // (3) sum a_i / 100 * x_ij <= u <=> sum a_i * x_ij <= 100 * u 137 | 138 | int offset1 = n; 139 | int offset2 = offset1 + m; 140 | int offset3 = offset2 + m; 141 | 142 | lp.set_b(offset1 + j, demand[j]); // (1) 143 | lp.set_b(offset2 + j, -demand[j]); // (2) 144 | lp.set_b(offset3 + j, 100 * upperAlcoholLimit[j]); // (3) 145 | 146 | for (int i = 0; i < n; ++i) { 147 | int x_ij = i * m + j; 148 | lp.set_a(x_ij, offset1 + j, 1); // (1) 149 | lp.set_a(x_ij, offset2 + j, -1); // (2) 150 | lp.set_a(x_ij, offset3 + j, alcoholPercentage[i]); // (3) 151 | } 152 | } 153 | 154 | // max sum profit_ij * x_ij <=> min sum -profit_ij * x_ij 155 | for (int i = 0; i < n; ++i) { 156 | for (int j = 0; j < m; ++j) { 157 | int x_ij = i * m + j; 158 | lp.set_c(x_ij, -profit[i][j]); 159 | } 160 | } 161 | 162 | // Solve it 163 | Solution solution = CGAL::solve_nonnegative_linear_program(lp, ET()); 164 | 165 | if (solution.is_infeasible()) { 166 | cout << "RIOT!" << endl; 167 | } else { // Can not be unbounded as there is only a limited supply 168 | cout << fixed << setprecision(0) << floor_to_double(solution.objective_value() / ET(-100)) << endl; 169 | } 170 | } 171 | 172 | int main() { 173 | ios_base::sync_with_stdio(false); 174 | int t; cin >> t; 175 | while (t--) { 176 | solve(); 177 | } 178 | return 0; 179 | } -------------------------------------------------------------------------------- /tasks/algocoon.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/algocoon.pdf -------------------------------------------------------------------------------- /tasks/ant_challenge.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/ant_challenge.pdf -------------------------------------------------------------------------------- /tasks/antenna.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/antenna.pdf -------------------------------------------------------------------------------- /tasks/asterix_the_gaul.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/asterix_the_gaul.pdf -------------------------------------------------------------------------------- /tasks/attack_of_the_clones.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/attack_of_the_clones.pdf -------------------------------------------------------------------------------- /tasks/beach_bars.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/beach_bars.pdf -------------------------------------------------------------------------------- /tasks/bistro.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/bistro.pdf -------------------------------------------------------------------------------- /tasks/boats.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/boats.pdf -------------------------------------------------------------------------------- /tasks/buddies.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/buddies.pdf -------------------------------------------------------------------------------- /tasks/build_the_sum.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/build_the_sum.pdf -------------------------------------------------------------------------------- /tasks/burning_coins.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/burning_coins.pdf -------------------------------------------------------------------------------- /tasks/carsharing.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/carsharing.pdf -------------------------------------------------------------------------------- /tasks/casino.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/casino.pdf -------------------------------------------------------------------------------- /tasks/chariot_race.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/chariot_race.pdf -------------------------------------------------------------------------------- /tasks/clues.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/clues.pdf -------------------------------------------------------------------------------- /tasks/deck_of_cards.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/deck_of_cards.pdf -------------------------------------------------------------------------------- /tasks/defensive_line.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/defensive_line.pdf -------------------------------------------------------------------------------- /tasks/diet.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/diet.pdf -------------------------------------------------------------------------------- /tasks/dominoes.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/dominoes.pdf -------------------------------------------------------------------------------- /tasks/even_matrices.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/even_matrices.pdf -------------------------------------------------------------------------------- /tasks/even_pairs.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/even_pairs.pdf -------------------------------------------------------------------------------- /tasks/evolution.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/evolution.pdf -------------------------------------------------------------------------------- /tasks/first_hit.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/first_hit.pdf -------------------------------------------------------------------------------- /tasks/first_steps.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/first_steps.pdf -------------------------------------------------------------------------------- /tasks/fleetrace.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/fleetrace.pdf -------------------------------------------------------------------------------- /tasks/germs.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/germs.pdf -------------------------------------------------------------------------------- /tasks/h1n1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/h1n1.pdf -------------------------------------------------------------------------------- /tasks/hand.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/hand.pdf -------------------------------------------------------------------------------- /tasks/hiking_maps.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/hiking_maps.pdf -------------------------------------------------------------------------------- /tasks/hit.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/hit.pdf -------------------------------------------------------------------------------- /tasks/hongkong.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/hongkong.pdf -------------------------------------------------------------------------------- /tasks/idefix.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/idefix.pdf -------------------------------------------------------------------------------- /tasks/importantbridges.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/importantbridges.pdf -------------------------------------------------------------------------------- /tasks/inball.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/inball.pdf -------------------------------------------------------------------------------- /tasks/india.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/india.pdf -------------------------------------------------------------------------------- /tasks/iron_islands.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/iron_islands.pdf -------------------------------------------------------------------------------- /tasks/kingdom_defence.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/kingdom_defence.pdf -------------------------------------------------------------------------------- /tasks/knights.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/knights.pdf -------------------------------------------------------------------------------- /tasks/lannister.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/lannister.pdf -------------------------------------------------------------------------------- /tasks/legions.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/legions.pdf -------------------------------------------------------------------------------- /tasks/lestrade.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/lestrade.pdf -------------------------------------------------------------------------------- /tasks/marathon.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/marathon.pdf -------------------------------------------------------------------------------- /tasks/maximizeit.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/maximizeit.pdf -------------------------------------------------------------------------------- /tasks/meereen.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/meereen.pdf -------------------------------------------------------------------------------- /tasks/motorcycles.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/motorcycles.pdf -------------------------------------------------------------------------------- /tasks/moving_books.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/moving_books.pdf -------------------------------------------------------------------------------- /tasks/new_york.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/new_york.pdf -------------------------------------------------------------------------------- /tasks/octopussy.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/octopussy.pdf -------------------------------------------------------------------------------- /tasks/placing_knights.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/placing_knights.pdf -------------------------------------------------------------------------------- /tasks/punch.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/punch.pdf -------------------------------------------------------------------------------- /tasks/radiation.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/radiation.pdf -------------------------------------------------------------------------------- /tasks/real_estate.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/real_estate.pdf -------------------------------------------------------------------------------- /tasks/return_of_the_jedi.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/return_of_the_jedi.pdf -------------------------------------------------------------------------------- /tasks/russia.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/russia.pdf -------------------------------------------------------------------------------- /tasks/san francisco.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/san francisco.pdf -------------------------------------------------------------------------------- /tasks/search_snippets.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/search_snippets.pdf -------------------------------------------------------------------------------- /tasks/secret_service.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/secret_service.pdf -------------------------------------------------------------------------------- /tasks/shopping_trip.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/shopping_trip.pdf -------------------------------------------------------------------------------- /tasks/sith.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/sith.pdf -------------------------------------------------------------------------------- /tasks/surveillance.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/surveillance.pdf -------------------------------------------------------------------------------- /tasks/switzerland.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/switzerland.pdf -------------------------------------------------------------------------------- /tasks/the_great_game.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/the_great_game.pdf -------------------------------------------------------------------------------- /tasks/tiles.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/tiles.pdf -------------------------------------------------------------------------------- /tasks/tracking.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/tracking.pdf -------------------------------------------------------------------------------- /tasks/worldcup.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsparber/algolab/9781eb5c7444236f796f167f1f39fc9d913e5c53/tasks/worldcup.pdf --------------------------------------------------------------------------------