├── README.md ├── hack ├── Asterix the Gaul.cpp ├── DHL.cpp └── readme.md ├── problems-of-the-week ├── Augean Stable.cpp ├── Ceryneian Hind.cpp ├── Deck of Cards.cpp ├── Greyjoy.cpp ├── Hands.cpp ├── Knights.cpp ├── Ludo Bagman.cpp ├── Motorcycles.cpp ├── Octopussy.cpp ├── Rubeus Hagrid.cpp ├── San Francisco.cpp ├── Strikesback.cpp └── Tracking.cpp ├── problems ├── algocoön group.pdf ├── ant challenge.pdf ├── antenna.pdf ├── asterix and the chariot race.pdf ├── asterix in switzerland.pdf ├── asterix_the_gaul.pdf ├── beach_bars.pdf ├── bistro.pdf ├── boats.pdf ├── buddy selection.pdf ├── build_the_sum.pdf ├── burning_coins.pdf ├── car sharing.pdf ├── casino royale.pdf ├── ceryneian hind.pdf ├── clues.pdf ├── coin cossing tournament.pdf ├── deck_of_cards.pdf ├── dhl.pdf ├── diet.pdf ├── dominoes.pdf ├── even_matrices.pdf ├── even_pairs.pdf ├── evolution.pdf ├── first steps with bgl.pdf ├── firsthit.pdf ├── fleetrace.pdf ├── germs.pdf ├── greyjoy.pdf ├── h1n1.pdf ├── hands.pdf ├── hiking-maps.pdf ├── hit.pdf ├── idefix and the mansion of the gods.pdf ├── important bridges.pdf ├── inball.pdf ├── knights.pdf ├── light the stage.pdf ├── london.pdf ├── lord voldemort.pdf ├── ludo bagman.pdf ├── marathon.pdf ├── motorcycles.pdf ├── moving_books.pdf ├── nemean lion.pdf ├── new york.pdf ├── octopussy.pdf ├── on her majesty’s secret service.pdf ├── placing knights.pdf ├── real estate market.pdf ├── revenge of the sith.pdf ├── rubeus_hagrid.pdf ├── san_francisco.pdf ├── search_snippets.pdf ├── severus_snape.pdf ├── shopping trip.pdf ├── strikesback.pdf ├── suez.pdf ├── the augean stables.pdf ├── the fighting pits of meereen .pdf ├── the_great_game.pdf ├── tiles.pdf ├── tracking.pdf ├── what is the maximum.pdf └── world cup.pdf ├── resume └── README.md ├── week1 ├── Build the Sum.cpp ├── Dominoes.cpp ├── Even Matrices.cpp └── Even Pairs.cpp ├── week10 ├── Clues.cpp ├── DHL.cpp ├── Fleetrace.cpp └── New York.cpp ├── week11 ├── Asterix in Switzerland.cpp ├── Sith.cpp ├── The Fighting Pits of Meereen.cpp └── Worldcup.cpp ├── week12 ├── Car Sharing.cpp ├── Lord Voldemort.cpp ├── Nemean Lion.cpp ├── Nemean Lion_4.cpp └── On Her Majesty's Secret Service.cpp ├── week13 ├── Asterix and the Chariot Race.cpp ├── Evolution.cpp ├── Idéfix.cpp └── Marathon.cpp ├── week2 ├── Beach Bars.cpp ├── Burning Coins.cpp ├── Search Snippets.cpp └── The Great Game.cpp ├── week3 ├── Ant Challenge.cpp ├── Buddy Selection.cpp ├── First steps with BGL.cpp └── Important Bridges.cpp ├── week4 ├── Antenna.cpp ├── First Hit.cpp ├── Hiking Map.cpp └── Hit.cpp ├── week5 ├── Asterix the Gaul.cpp ├── Boats.cpp ├── Moving Books.cpp └── Severus Snape.cpp ├── week6 ├── Diet.cpp ├── Inball.cpp ├── Maximize it!.cpp └── Suez.cpp ├── week7 ├── Coin Tossing Tournament.cpp ├── London.cpp ├── Shopping Trip.cpp └── Tiles.cpp ├── week8 ├── Bistro.cpp ├── Germs.cpp ├── H1N1.cpp └── Light the Stage.cpp └── week9 ├── Algocoon.cpp ├── Casino Royale.cpp ├── Placing Knights.cpp └── Real Estate Market.cpp /README.md: -------------------------------------------------------------------------------- 1 | # ALGO Lab ETHZ 2022 2 | 3 |
4 | 5 | ![C++](https://img.shields.io/badge/c++-%2300599C.svg?style=for-the-badge&logo=c%2B%2B&logoColor=white) ![CMake](https://img.shields.io/badge/CMake-%23008FBA.svg?style=for-the-badge&logo=cmake&logoColor=white) 6 | 7 |
8 | 9 | My solutions for the course algo lab 2022 given at ETHZ. This course deals with various topics such as dynamic programming, binary search, greedy algorithms, graphs, flows, geometry and linear programming. 10 | 11 |
12 | 13 | [Link to the course](https://cadmo.ethz.ch/education/lectures/HS22/algolab/index.html) • [Boost Graph Library](https://www.boost.org/doc/libs/1_78_0/libs/graph/doc/index.html) • [CGAL](https://www.cgal.org/) 14 | 15 |
16 | 17 |
18 | 19 | ## Problems with solutions 20 | 21 | | Name | Challenge | Solution | Points | Week | Theme | 22 | | ------------- |---------------------- |------------------|-----------------|------------------|-----------------------| 23 | | Build the sum | [File](./problems/build_the_sum.pdf) | [C++ code](./week1/Build%20the%20Sum.cpp) | 100 | 1 | STL | 24 | | Dominoes | [File](./problems/dominoes.pdf) | [C++ code](./week1/Dominoes.cpp) | 100 | 1 | STL | 25 | | Even Pairs | [File](./problems/even_pairs.pdf) | [C++ code](./week1/Even%20Pairs.cpp) | 100 | 1 | Combinatorics - Prefix sum | 26 | | Even Matrices | [File](./problems/even_matrices.pdf) | [C++ code](./week1/Even%20Matrices.cpp) | 100 | 1 | Combinatorics - Prefix sum | 27 | | Beach Bars | [File](./problems/beach_bars.pdf) | [C++ code](./week2/Beach%20Bars.cpp) | 100 | 2 | Two pointers | 28 | | Burning Coins | [File](./problems/burning_coins.pdf) | [C++ code](./week2/Burning%20Coins.cpp) | 100 | 2 | DP | 29 | | Search Snippets | [File](./problems/search_snippets.pdf) | [C++ code](./week2/Search%20Snippets.cpp) | 100 | 2 | Two pointers | 30 | | The Great Game | [File](./problems/the_great_game.pdf) | [C++ code](./week2/The%20Great%20Game.cpp) | 100 | 2 | DP | 31 | | Ant Challenge | [File](./problems/ant%20challenge.pdf) | [C++ code](./week3/Ant%20Challenge.cpp) | 100 | 3 | Graph - MST - Shortest Path | 32 | | Buddy Selection | [File](./problems/buddy%20selection.pdf) | [C++ code](./week3/Buddy%20Selection.cpp) | 100 | 3 | Graph - Matching | 33 | | First step with BGL | [File](./problems/first%20steps%20with%20bgl.pdf) | [C++ code](./week3/First%20steps%20with%20BGL.cpp) | 100 | 3 | Graph - BGL | 34 | | Important Bridges | [File](./problems/important%20bridges.pdf) | [C++ code](./week3/Important%20Bridges.cpp) | 100 | 3 | Graph - DFS | 35 | | Antenna | [File](./problems/antenna.pdf) | [C++ code](./week4/Antenna.cpp) | 100 | 4 | Geometry | 36 | | First Hit | [File](./problems/firsthit.pdf) | [C++ code](./week4/First%20Hit.cpp) | 100 | 4 | Geometry | 37 | | Hiking Map | [File](./problems/hiking-maps.pdf) | [C++ code](./week4/Hiking%20Map.cpp) | 100 | 4 | Geometry - Two pointers | 38 | | Hit | [File](./problems/hit.pdf) | [C++ code](./week4/First%20Hit.cpp) | 100 | 4 | Geometry | 39 | | Asterix the Gaul | [File](./problems/asterix_the_gaul.pdf) | [C++ code](./week5/Asterix%20the%20Gaul.cpp) | 100 | 5 | Binary Search - Split & List | 40 | | Boats | [File](./problems/boats.pdf) | [C++ code](./week5/Boats.cpp) | 100 | 5 | Greedy | 41 | | Moving Books | [File](./problems/moving_books.pdf) | [C++ code](./week5/Moving%20Books.cpp) | 100 | 5 | Greedy | 42 | | Severus Snape | [File](./problems/severus_snape.pdf) | [C++ code](./week5/Severus%20Snape.cpp) | 100 | 5 | Greedy - DP | 43 | | Diet | [File](./problems/diet.pdf) | [C++ code](./week6/Diet.cpp) | 100 | 6 | Linear programming | 44 | | Inball | [File](./problems/inball.pdf) | [C++ code](./week6/Inball.cpp) | 100 | 6 | Linear programming | 45 | | Maximize it!| [File](./problems/what%20is%20the%20maximum.pdf) | [C++ code](./week6/Maximize%20it!.cpp) | 100 | 6 | Linear programming | 46 | | Suez | [File](./problems/suez.pdf) | [C++ code](./week6/Suez.cpp) | 100 | 6 | Linear programming | 47 | | Coin Tossing Tournament | [File](./problems/coin%20cossing%20tournament.pdf) | [C++ code](./week7/Coin%20Tossing%20Tournament.cpp) | 100 | 7 | Flow | 48 | | London | [File](./problems/london.pdf) | [C++ code](./week7/London.cpp) | 100 | 7 | Flow | 49 | | Shopping Trip | [File](./problems/shopping%20trip.pdf) | [C++ code](./week7/Shopping%20Trip.cpp) | 100 | 7 | Flow | 50 | | Tiles | [File](./problems/tiles.pdf) | [C++ code](./week7/Tiles.cpp) | 100 | 7 | Flow | 51 | | Bistro | [File](./problems/bistro.pdf) | [C++ code](./week8/Bistro.cpp) | 100 | 8 | Advanced geometry | 52 | | Germs | [File](./problems/germs.pdf) | [C++ code](./week8/Germs.cpp) | 100 | 8 | Advanced geometry | 53 | | H1N1 | [File](./problems/h1n1.pdf) | [C++ code](./week8/H1N1.cpp) | 100 | 8 | Advanced geometry | 54 | | Light the Stage | [File](./problems/light%20the%20stage.pdf) | [C++ code](./week8/Light%20the%20Stage.cpp) | 100 | 8 | Advanced geometry | 55 | | Algocoon | [File](./problems/algoco%C3%B6n%20group.pdf) | [C++ code](./week9/Algocoon.cpp) | 100 | 9 | Advanced flows | 56 | | Casino Royale | [File](./problems/casino%20royale.pdf) | [C++ code](./week9/Casino%20Royale.cpp) | 100 | 9 | Advanced flows | 57 | | Placing Knights | [File](./problems/placing%20knights.pdf) | [C++ code](./week9/Placing%20Knights.cpp) | 100 | 9 | Advanced flows | 58 | | Real Estate Market | [File](./problems/real%20estate%20market.pdf) | [C++ code](./week9/Real%20Estate%20Market.cpp) | 100 | 9 | Advanced flows | 59 | | Clues | [File](./problems/clues.pdf) | [C++ code](./week10/Clues.cpp) | 100 | 10 | Graphs - Matchings - Advanced geometry | 60 | | DHL | [File](./problems/dhl.pdf) | [C++ code](./week10/DHL.cpp) | 100 | 10 | DP | 61 | | New York | [File](./problems/new%20york.pdf) | [C++ code](./week10/New%20York.cpp) | 100 | 10 | Two pointers - Graph - DFS | 62 | | Fleetrace | [File](./problems/fleetrace.pdf) | [C++ code](./week10/Fleetrace.cpp) | 100 | 10 | Advanced flows | 63 | | Asterix in Switzerland | [File](./problems/asterix%20in%20switzerland.pdf) | [C++ code](./week11/Asterix%20in%20Switzerland.cpp) | 100 | 11 | Flow | 64 | | Sith | [File](./problems/revenge%20of%20the%20sith.pdf) | [C++ code](./week11/Sith.cpp) | 100 | 11 | Advanced geometry - Graph - Binary search | 65 | | The Fighting Pits of Meereen | [File](./problems/the%20fighting%20pits%20of%20meereen%20.pdf) | [C++ code](./week11/The%20Fighting%20Pits%20of%20Meereen.cpp) | 100 | 11 | DP | 66 | | World Cup | [Files](./problems/world%20cup.pdf) | [C++ code](./week11/Worldcup.cpp) | 100 | 11 | Advanced geometry - Linear programming 67 | | Car Sharing | [Files](./problems/car%20sharing.pdf) | [C++ code](./week12/Car%20Sharing.cpp) | 100 | 12 | Advanced flows 68 | | Lord Voldemort | [Files](./problems/lord%20voldemort.pdf) | [C++ code](./week12/Lord%20Voldemort.cpp) | 100 | 12 | DP 69 | | On Her Majesty's Secret Service | [Files](./problems/on%20her%20majesty%E2%80%99s%20secret%20service.pdf) | [C++ code](./week12/On%20Her%20Majesty's%20Secret%20Service.cpp) | 100 | 12 | Graph - BS 70 | | Nemean Lion| [Files](./problems/nemean%20lion.pdf) | [C++ code](./week12/Nemean%20Lion.cpp) | 100 | 12 | Advanced geometry 71 | | Marathon | [Files](./problems/marathon.pdf) | [C++ code](./week13/Marathon.cpp) | 100 | 13 | Shortest path - flows 72 | | Asterix and the Chariot Race | [Files](./problems/asterix%20and%20the%20chariot%20race.pdf) | [C++ code](./week13/Asterix%20and%20the%20Chariot%20Race.cpp) | 100 | 13 | DP - Trees 73 | | Evolution | [Files](./problems/evolution.pdf) | [C++ code](./week13/Evolution.cpp) | 100 | 13 | Binary Search - Trees 74 | | Idéfix | [Files](./problems/idefix%20and%20the%20mansion%20of%20the%20gods.pdf) | [C++ code](./week13/Id%C3%A9fix.cpp) | 100 | 13 | Advanced geometry - BS 75 | 76 | 77 | ## Problems of the week with solutions 78 | 79 | | Name | Challenge | Solution | Points | Week | Theme | 80 | | ------------- |---------------------- |------------------|-----------------|------------------|-----------------------| 81 | | Deck of Cards | [File](./problems/deck_of_cards.pdf) | [C++ code](./problems-of-the-week/Deck%20of%20Cards.cpp) | 100 | 2 | Two pointers | 82 | | San Francisco | [File](./problems/san_francisco.pdf) | [C++ code](./problems-of-the-week/San%20Francisco.cpp) | 100 | 3 | DP - Graph | 83 | | Greyjoy | [File](./problems/greyjoy.pdf) | [C++ code](./problems-of-the-week/Greyjoy.cpp) | 100 | 4 | Two pointers - Sorting | 84 | | Tracking | [File](./problems/tracking.pdf) | [C++ code](./problems-of-the-week/Tracking.cpp) | 100 | 5 | Graph - Shortest Path | 85 | | Motorcycles| [File](./problems/motorcycles.pdf) | [C++ code](./problems-of-the-week/Motorcycles.cpp) | 100 | 6 | Geometry | 86 | | Octopussy | [File](./problems/octopussy.pdf) | [C++ code](./problems-of-the-week/Octopussy.cpp) | 100 | 7 | Greedy | 87 | | Augean Stable | [File](./problems/the%20augean%20stables.pdf) | [C++ code](./problems-of-the-week/Augean%20Stable.cpp) | 100 | 8 | Linear programming | 88 | | Knights | [File](./problems/knights.pdf) | [C++ code](./problems-of-the-week/Knights.cpp) | 100 | 9 | Flows | 89 | | Hands | [File](./problems/hands.pdf) | [C++ code](./problems-of-the-week/Hands.cpp) | 100 | 10 | Union find & Advanced geometry | 90 | | Ceryneian Hind | [File](./problems/ceryneian%20hind.pdf) | [C++ code](./problems-of-the-week/Ceryneian%20Hind.cpp) | 100 | 11 | Flows | 91 | | Rubeus Hagrid | [File](./problems/rubeus_hagrid.pdf) | [C++ code](./problems-of-the-week/Rubeus%20Hagrid.cpp) | 100 | 12 | Greedy | 92 | | Strikesback | [File](./problems/strikesback.pdf) | [C++ code](./problems-of-the-week/Strikesback.cpp) | 100 | 13 | Advanced geometry & Linear programming | 93 | | Ludo Bagman | [File](./problems/ludo%20bagman.pdf) | [C++ code](./problems-of-the-week/Ludo%20Bagman.cpp) | 100 | 14 | Advanced flows | 94 | 95 |
96 | -------------------------------------------------------------------------------- /hack/Asterix the Gaul.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define int long 4 | 5 | using namespace std; 6 | 7 | struct Move { 8 | int d; 9 | int t; 10 | }; 11 | 12 | int n,m,D,T; 13 | vector movement; 14 | vector bonus; 15 | 16 | void generate(vector&set, int from, int to, int b, Move mv) { 17 | if(mv.t > T) return; 18 | if(from == to) { 19 | set.push_back(mv); 20 | return; 21 | } 22 | 23 | Move new_move = Move{mv.d+movement[from].d+b,mv.t+movement[from].t}; 24 | 25 | generate(set,from+1,to,b,new_move); 26 | generate(set,from+1,to,b,mv); 27 | } 28 | 29 | bool compute(int b) { 30 | 31 | vector subset1(0); 32 | vector subset2(0); 33 | 34 | generate(subset1,0,n/2,b,Move{0,0}); 35 | generate(subset2,n/2,n,b,Move{0,0}); 36 | 37 | auto comp = [](Move m1, Move m2){ 38 | return m1.t < m2.t; 39 | }; 40 | 41 | sort(subset1.begin(),subset1.end(),comp); 42 | sort(subset2.begin(),subset2.end(),comp); 43 | 44 | for(int i = 1; i < subset1.size();i++) subset1[i].d = max(subset1[i].d,subset1[i-1].d); 45 | for(int i = 1; i < subset2.size();i++) subset2[i].d = max(subset2[i].d,subset2[i-1].d); 46 | 47 | for(auto move : subset1) { 48 | auto move2 = lower_bound(subset2.begin(), subset2.end(), T - move.t,[&](const Move &move, int value){ 49 | return move.t < value; 50 | }) - 1; 51 | 52 | if(move.d + move2->d >= D) 53 | return true; 54 | } 55 | 56 | return false; 57 | } 58 | 59 | void solve() { 60 | cin >> n >> m >> D >> T; 61 | 62 | movement = vector(n); 63 | for(int i = 0; i < n;i++) cin >> movement[i].d >> movement[i].t; 64 | 65 | bonus = vector(m+2); 66 | for(int i = 1; i <= m;i++) cin >> bonus[i]; 67 | bonus.back() = 0; 68 | 69 | // Binary search over the solution space 70 | int start = 0; 71 | int end = m+2; 72 | while(start != end) { 73 | int middle = (start + end) / 2; 74 | if(compute(bonus[middle])) { 75 | end = middle; 76 | } else { 77 | start = middle+1; 78 | } 79 | } 80 | 81 | if(start == m+2) { 82 | cout << "Panoramix captured" << "\n"; 83 | } else { 84 | cout << start << "\n"; 85 | } 86 | } 87 | 88 | signed main() { 89 | ios_base::sync_with_stdio(false); 90 | cin.tie(0); 91 | 92 | int t; 93 | cin >> t; 94 | 95 | while(t--) 96 | solve(); 97 | } 98 | -------------------------------------------------------------------------------- /hack/DHL.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | void solve() { 6 | 7 | int n; 8 | cin >> n; 9 | 10 | vector a(n+1,0); 11 | vector b(n+1,0); 12 | 13 | for(int i = 1; i <= n;i++) { 14 | cin >> a[i]; 15 | a[i] += a[i-1]; 16 | } 17 | for(int j = 1; j <= n;j++) { 18 | cin >> b[j]; 19 | b[j] += b[j-1]; 20 | } 21 | 22 | vector> dp(n+1,vector(n+1,INT_MAX)); 23 | dp[0][0] = 0; 24 | 25 | for(int i = 1; i <= n;i++) { 26 | for(int j = 1; j <= n;j++) { 27 | for(int k = i-1; k >= 0;k--) { 28 | for(int l = j-1; l >= 0;l--) { 29 | if(dp[k][l] != INT_MAX) { 30 | dp[i][j] = min(dp[i][j],dp[k][l] + (a[i]-a[k]-(i-k)) * (b[j]-b[l]-(j-l)) ); 31 | } 32 | if((a[i]-a[k]-(i-k)) >= 50 && (b[j]-b[l]-(j-l)) >= 50) { 33 | break; 34 | } 35 | } 36 | } 37 | } 38 | } 39 | 40 | cout << dp.back().back() << "\n"; 41 | } 42 | 43 | int main() { 44 | 45 | ios_base::sync_with_stdio(false); 46 | cin.tie(0); 47 | 48 | int t; 49 | cin >> t; 50 | 51 | while(t--) 52 | solve(); 53 | } 54 | -------------------------------------------------------------------------------- /hack/readme.md: -------------------------------------------------------------------------------- 1 | # Hacks 2 | 3 | ### Asterix and the Gaul 4 | 5 | This code fails the sample test but get 100 pts 6 | 7 | ### DHL 8 | 9 | The submitted code is wrong but get 99 pts (last point is a challenge) 10 | -------------------------------------------------------------------------------- /problems-of-the-week/Augean Stable.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | typedef int IT; 9 | typedef CGAL::Gmpz ET; 10 | 11 | typedef CGAL::Quadratic_program Program; 12 | typedef CGAL::Quadratic_program_solution Solution; 13 | 14 | typedef struct stall { 15 | int x,k,l,m; 16 | } stall; 17 | 18 | const int h1 = 0; 19 | const int h2 = 1; 20 | const int h3 = 2; 21 | 22 | bool possible(const vector &stalls, int a, int p) { 23 | 24 | Program lp(CGAL::SMALLER, true, 0, true, 1); 25 | 26 | for(int i = 0; i < stalls.size();i++) { 27 | lp.set_a(h1,i,-stalls[i].k - a*a); 28 | lp.set_a(h2,i,-stalls[i].l - p*p); 29 | lp.set_a(h3,i,-stalls[i].m - a*p); 30 | lp.set_b(i,-stalls[i].x); 31 | } 32 | 33 | Solution s = CGAL::solve_linear_program(lp, ET()); 34 | return !s.is_infeasible(); 35 | } 36 | 37 | void solve() { 38 | 39 | int n; 40 | cin >> n; 41 | 42 | vector stalls(n); 43 | 44 | for(int i = 0; i < n;i++) { 45 | int f,c,k,l,m; 46 | cin >> f >> c >> k >> l >> m; 47 | stalls[i] = {f-c,k,l,m}; 48 | } 49 | 50 | vector a(25); 51 | vector p(25); 52 | 53 | for(int i = 1; i <= 24;i++) 54 | cin >> a[i]; 55 | 56 | for(int i = 1; i <= 24;i++) 57 | cin >> p[i]; 58 | 59 | partial_sum(a.begin(), a.end(), a.begin()); 60 | partial_sum(p.begin(), p.end(), p.begin()); 61 | 62 | int best_score = INT_MAX; 63 | 64 | int left = 0; 65 | int right = 48; 66 | int bound = 24; 67 | 68 | vector cache(25,-1); 69 | 70 | while(left <= right) { 71 | 72 | int hours = (left + right + 1) / 2; 73 | bool can = false; 74 | 75 | for(int ai = max(0, hours - bound); ai <= min(hours,bound); ai++) { 76 | const int pi = hours - ai; 77 | 78 | if (cache[ai] > pi) 79 | continue; 80 | 81 | if(possible(stalls,a[ai],p[pi])) { 82 | can = true; 83 | break; 84 | } 85 | else { 86 | cache[ai] = max(cache[ai], pi); 87 | } 88 | } 89 | if(can) { 90 | best_score = hours; 91 | right = hours-1; 92 | } 93 | else { 94 | left = hours+1; 95 | } 96 | } 97 | 98 | if(best_score == INT_MAX) { 99 | cout << "Impossible!" << "\n"; 100 | } 101 | else { 102 | cout << best_score << "\n"; 103 | } 104 | 105 | return; 106 | } 107 | 108 | signed main() { 109 | 110 | ios_base::sync_with_stdio(false); 111 | cin.tie(NULL); 112 | 113 | int t; 114 | cin >> t; 115 | 116 | while(t--) 117 | solve(); 118 | 119 | } 120 | -------------------------------------------------------------------------------- /problems-of-the-week/Ceryneian Hind.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | typedef boost::adjacency_list_traits traits; 8 | typedef boost::adjacency_list>>> graph; 12 | 13 | typedef traits::vertex_descriptor vertex_desc; 14 | typedef traits::edge_descriptor edge_desc; 15 | 16 | class edge_adder { 17 | graph &G; 18 | 19 | public: 20 | explicit edge_adder(graph &G) : G(G) {} 21 | 22 | void add_edge(int from, int to,int capacity) { 23 | auto c_map = boost::get(boost::edge_capacity, G); 24 | auto r_map = boost::get(boost::edge_reverse, G); 25 | const auto e = boost::add_edge(from, to, G).first; 26 | const auto rev_e = boost::add_edge(to, from, G).first; 27 | c_map[e] = capacity; 28 | c_map[rev_e] = 0; 29 | r_map[e] = rev_e; 30 | r_map[rev_e] = e; 31 | } 32 | }; 33 | 34 | void solve() { 35 | 36 | int n,m; 37 | cin >> n >> m; 38 | 39 | vector scores = vector(n); 40 | for(int i = 0; i < n;i++) cin >> scores[i]; 41 | 42 | int sum_positive = accumulate(scores.begin(),scores.end(),0,[](int a, int b) -> int { 43 | return max(a,0)+max(b,0); 44 | }); 45 | 46 | graph G(n); 47 | edge_adder adder(G); 48 | 49 | auto v_source = boost::add_vertex(G); 50 | auto v_sink = boost::add_vertex(G); 51 | 52 | for(int i = 0; i < m;i++) { 53 | int u,v; 54 | cin >> u >> v; 55 | adder.add_edge(u,v,sum_positive); 56 | } 57 | 58 | for(int i = 0; i < n;i++) { 59 | if(scores[i] >= 0) { 60 | adder.add_edge(v_source,i,scores[i]); 61 | } else { 62 | adder.add_edge(i,v_sink,abs(scores[i])); 63 | } 64 | } 65 | 66 | int flow = boost::push_relabel_max_flow(G,v_source,v_sink); 67 | int ans = sum_positive - flow; 68 | 69 | if(ans == 0) { 70 | cout << "impossible" << "\n"; 71 | } else { 72 | cout << ans << "\n"; 73 | } 74 | } 75 | 76 | int main() { 77 | 78 | ios_base::sync_with_stdio(false); 79 | cin.tie(0); 80 | 81 | int t; cin >> t; 82 | while(t--) 83 | solve(); 84 | 85 | return 0; 86 | } 87 | -------------------------------------------------------------------------------- /problems-of-the-week/Deck of Cards.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | 9 | void solve() { 10 | 11 | int n,k; 12 | cin >> n >> k; 13 | 14 | vector a(0); 15 | 16 | for(int i = 0; i < n;i++) { 17 | int tmp; 18 | cin >> tmp; 19 | a.push_back(tmp); 20 | } 21 | 22 | int left = -1; 23 | int right = 0; 24 | 25 | int best = INT_MAX; 26 | int l1 = -1,l2 = -1; 27 | 28 | int sum = 0; 29 | 30 | while(left != n-1) { 31 | 32 | left++; 33 | sum += a[left]; 34 | 35 | if(abs(sum - k) < best) { 36 | best = abs(sum - k); 37 | l1 = right; 38 | l2 = left; 39 | } 40 | 41 | while(left != right && sum - k > 0) { 42 | 43 | sum -= a[right]; 44 | right++; 45 | 46 | if(abs(sum - k) < best) { 47 | best = abs(sum - k); 48 | l1 = right; 49 | l2 = left; 50 | } 51 | } 52 | 53 | } 54 | 55 | cout << l1 << " " << l2 << "\n"; 56 | } 57 | 58 | int main() { 59 | 60 | int t; 61 | cin >> t; 62 | 63 | while(t--) 64 | solve(); 65 | 66 | return 0; 67 | } 68 | -------------------------------------------------------------------------------- /problems-of-the-week/Greyjoy.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | #define int long long 8 | 9 | typedef struct { 10 | int value; 11 | int position; 12 | int way; 13 | } island; 14 | 15 | void solve() { 16 | 17 | int n,k,w; 18 | cin >> n >> k >> w; 19 | 20 | vector c(n); 21 | for(int i = 0; i < n;i++) { 22 | cin >> c[i]; 23 | } 24 | 25 | vector> ways(w,vector(0)); 26 | vector islands(0); 27 | 28 | for(int i = 0; i < w;i++) { 29 | int l; 30 | cin >> l; 31 | vector tmp(l,0); 32 | int sum = 0; 33 | for(int j = 0; j < l;j++) { 34 | cin >> tmp[j]; 35 | if(j != 0) { 36 | sum += c[tmp[j]]; 37 | islands.push_back({sum,j,i}); 38 | } 39 | } 40 | ways[i] = tmp; 41 | } 42 | 43 | int best = 0; 44 | 45 | for(int i = 0; i < w;i++) { 46 | 47 | int start = -1; 48 | int end = 0; 49 | int score = 0; 50 | 51 | int length = ways[i].size(); 52 | 53 | while(start < length - 1) { 54 | 55 | start++; 56 | score += c[ways[i][start]]; 57 | 58 | while(score > k) { 59 | score -= c[ways[i][end]]; 60 | end++; 61 | } 62 | 63 | if(score == k) { 64 | best = max(best,start - end + 1); 65 | } 66 | } 67 | } 68 | 69 | sort(islands.begin(),islands.end(),[](island a, island b) -> bool { 70 | return a.value < b.value; 71 | }); 72 | 73 | vector> is(1,{islands[0]}); 74 | 75 | for(int i = 1; i < islands.size();i++) { 76 | if(islands[i].value == islands[i-1].value) { 77 | is.back().push_back(islands[i]); 78 | } else{ 79 | is.push_back({islands[i]}); 80 | } 81 | } 82 | 83 | int left = 0; 84 | int right = is.size()-1; 85 | 86 | int goal = k - c[0]; 87 | 88 | while(left <= right) { 89 | if(is[left][0].value + is[right][0].value < goal) { 90 | left++; 91 | } 92 | else if(is[left][0].value + is[right][0].value > goal) { 93 | right--; 94 | } 95 | else { 96 | for(auto i1 : is[left]) { 97 | for(auto i2 : is[right]) { 98 | if(i1.way != i2.way && i1.value + i2.value == goal) { 99 | best = max(best,i1.position + i2.position + 1); 100 | } 101 | } 102 | } 103 | left++; 104 | right--; 105 | } 106 | } 107 | 108 | cout << best << endl; 109 | } 110 | 111 | signed main() { 112 | 113 | int t; 114 | cin >> t; 115 | 116 | while(t--) 117 | solve(); 118 | } 119 | -------------------------------------------------------------------------------- /problems-of-the-week/Hands.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #define int long 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 Triangulation; 17 | typedef CGAL::Point_2 Point; 18 | 19 | using namespace std; 20 | 21 | typedef struct Edge { 22 | int x; 23 | int y; 24 | int w; 25 | } Edge; 26 | 27 | int maxFamilies(vector &c, int k) { 28 | 29 | int o = c[k]; 30 | 31 | if(k == 4) { 32 | if(c[3] <= c[1]) { 33 | o += c[3]; 34 | o += ((c[1]-c[3])/2+c[2]) / 2; 35 | } 36 | else{ 37 | o += c[1]; 38 | o += ((c[3]-c[1])+c[2]) / 2; 39 | } 40 | } 41 | 42 | else if(k == 3) { 43 | if(c[2] <= c[1]) { 44 | o += c[2]; 45 | o += (c[1] - c[2]) / 3; 46 | } 47 | else { 48 | o += c[1]; 49 | o += (c[2] - c[1]) / 2; 50 | } 51 | } 52 | 53 | else if(k == 2) { 54 | o += c[1] / 2; 55 | } 56 | 57 | return o; 58 | } 59 | void solve() { 60 | 61 | int n,k,f0,s0; 62 | cin >> n >> k >> f0 >> s0; 63 | 64 | vector> points(n); 65 | for(int i = 0; i < n;i++) { 66 | int x,y; 67 | cin >> x >> y; 68 | points[i] = {Point(x,y),i}; 69 | } 70 | 71 | Triangulation t; 72 | t.insert(points.begin(),points.end()); 73 | 74 | vector edges(0); 75 | for(auto e = t.finite_edges_begin(); e != t.finite_edges_end(); ++e) { 76 | int p1 = e->first->vertex((e->second + 1) % 3)->info(); 77 | int p2 = e->first->vertex((e->second + 2) % 3)->info(); 78 | if(p1 > p2) swap(p1,p2); 79 | edges.push_back({p1,p2, long(t.segment(e).squared_length())}); 80 | } 81 | 82 | sort(edges.begin(),edges.end(),[](const Edge &e1, const Edge &e2) -> bool { 83 | return e1.w < e2.w; 84 | }); 85 | 86 | boost::disjoint_sets_with_storage<> uf(n); 87 | 88 | int n_components = n; 89 | 90 | vector sizeComponent(n,1); 91 | vector componentOfSize(k+1,0); 92 | componentOfSize[1] = n; 93 | 94 | int s_sol = 0; 95 | int f_sol = 0; 96 | 97 | for(auto e : edges) { 98 | // Get Index 99 | int c1 = uf.find_set(e.x); 100 | int c2 = uf.find_set(e.y); 101 | // Ignore if they are similar 102 | if(c1 == c2) continue; 103 | 104 | int fMax = maxFamilies(componentOfSize,k); 105 | 106 | // Case 1 107 | if(fMax >= f0) { 108 | s_sol = e.w; 109 | } 110 | // Case 2 111 | if(e.w >= s0) { 112 | f_sol = max(fMax,f_sol); 113 | } 114 | // Update the union find 115 | uf.link(c1,c2); 116 | int c = uf.find_set(c1); 117 | 118 | componentOfSize[sizeComponent[c1]]--; 119 | componentOfSize[sizeComponent[c2]]--; 120 | sizeComponent[c] = min(k,sizeComponent[c1] + sizeComponent[c2]); 121 | componentOfSize[sizeComponent[c]] += 1; 122 | 123 | n_components--; 124 | if(n_components == 1) break; 125 | } 126 | 127 | f_sol = max(maxFamilies(componentOfSize,k),f_sol); 128 | 129 | cout << s_sol << " " << f_sol << "\n"; 130 | 131 | return; 132 | } 133 | 134 | signed main() { 135 | 136 | ios_base::sync_with_stdio(false); 137 | cin.tie(0); 138 | 139 | int t; 140 | cin >> t; 141 | 142 | while(t--) 143 | solve(); 144 | 145 | return 0; 146 | } 147 | -------------------------------------------------------------------------------- /problems-of-the-week/Knights.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | #define int long 11 | 12 | typedef boost::adjacency_list_traits traits; 13 | typedef boost::adjacency_list>>> graph; 17 | 18 | typedef traits::vertex_descriptor vertex_desc; 19 | typedef traits::edge_descriptor edge_desc; 20 | 21 | class edge_adder { 22 | 23 | graph &G; 24 | 25 | public: 26 | explicit edge_adder(graph &G) : G(G) {} 27 | 28 | void add_edge(int from, int to, int weight) { 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] = weight; 34 | c_map[rev_e] = 0; 35 | r_map[e] = rev_e; 36 | r_map[rev_e] = e; 37 | } 38 | }; 39 | 40 | typedef struct Point { 41 | int x; 42 | int y; 43 | } Point; 44 | 45 | void solve() { 46 | 47 | int column,row,k,c; 48 | cin >> column >> row >> k >> c; 49 | 50 | vector positions(k); 51 | for(int i = 0; i < k;i++) { 52 | int x,y; cin >> x >> y; 53 | positions[i] = {x,y}; 54 | } 55 | 56 | if(column*row == 0) { 57 | cout << 0 << "\n"; 58 | return; 59 | } 60 | 61 | graph G(2*column*row); 62 | edge_adder adder(G); 63 | 64 | const vertex_desc v_source = boost::add_vertex(G); 65 | const vertex_desc v_sink = boost::add_vertex(G); 66 | 67 | const int size = row * column; 68 | 69 | // Add bind in and out in intersections 70 | for(int i = 0; i < row*column;i++) { 71 | adder.add_edge(i,i+size,c); 72 | } 73 | 74 | // Bind corridors with intersections 75 | for(int i = 0; i < row-1;i++) { 76 | for(int j = 0; j < column;j++) { 77 | const int i1 = i*column + j; 78 | const int i2 = (i+1)*column + j; 79 | adder.add_edge(i1 + size, i2, 1); 80 | adder.add_edge(i2 + size, i1, 1); 81 | } 82 | } 83 | 84 | for(int j = 0; j < row;j++) { 85 | for(int i = 0; i < column-1;i++) { 86 | const int i1 = j*column + i; 87 | const int i2 = j*column + i + 1; 88 | adder.add_edge(i1 + size, i2, 1); 89 | adder.add_edge(i2 + size, i1, 1); 90 | } 91 | } 92 | 93 | // Bind corridors with sink 94 | for(int i = 0; i < row;i++) { 95 | adder.add_edge(i*column + size,v_sink,1); 96 | adder.add_edge(i*column + column-1 + size,v_sink,1); 97 | } 98 | 99 | for(int i = 0; i < column;i++) { 100 | adder.add_edge(i + size,v_sink,1); 101 | adder.add_edge(column*(row-1) + i + size,v_sink,1); 102 | } 103 | 104 | // Bind starting points for knights 105 | for(int i = 0; i < k;i++) { 106 | adder.add_edge(v_source,positions[i].y * column + positions[i].x,1); 107 | } 108 | 109 | // Get the max flow & output it 110 | long flow = boost::push_relabel_max_flow(G, v_source, v_sink); 111 | cout << flow << "\n"; 112 | 113 | return; 114 | } 115 | 116 | signed main() { 117 | 118 | int t; 119 | cin >> t; 120 | 121 | while(t--) 122 | solve(); 123 | 124 | return 0; 125 | } 126 | -------------------------------------------------------------------------------- /problems-of-the-week/Ludo Bagman.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | typedef boost::adjacency_list_traits traits; 12 | typedef boost::adjacency_list > > > > graph; 17 | 18 | typedef boost::graph_traits::edge_descriptor edge_desc; 19 | typedef boost::graph_traits::out_edge_iterator out_edge_it; 20 | typedef traits::vertex_descriptor vertex_desc; 21 | 22 | 23 | class edge_adder { 24 | graph &G; 25 | 26 | public: 27 | explicit edge_adder(graph &G) : G(G) {} 28 | void add_edge(int from, int to, long capacity, long cost) { 29 | auto c_map = boost::get(boost::edge_capacity, G); 30 | auto r_map = boost::get(boost::edge_reverse, G); 31 | auto w_map = boost::get(boost::edge_weight, G); 32 | const edge_desc e = boost::add_edge(from, to, G).first; 33 | const edge_desc rev_e = boost::add_edge(to, from, G).first; 34 | c_map[e] = capacity; 35 | c_map[rev_e] = 0; 36 | r_map[e] = rev_e; 37 | r_map[rev_e] = e; 38 | w_map[e] = cost; 39 | w_map[rev_e] = -cost; 40 | } 41 | }; 42 | 43 | struct Match { 44 | int u; 45 | int v; 46 | int r; 47 | }; 48 | 49 | void solve() { 50 | 51 | int e,w,m,d,p,l; 52 | cin >> e >> w >> m >> d >> p >> l; 53 | 54 | vector matches = vector(m+d); 55 | for(int i = 0; i < m + d;i++) { 56 | cin >> matches[i].u; 57 | cin >> matches[i].v; 58 | cin >> matches[i].r; 59 | } 60 | 61 | graph G(2*(e+w)); 62 | edge_adder adder(G); 63 | 64 | vertex_desc v_source = boost::add_vertex(G); 65 | vertex_desc v_source_2 = boost::add_vertex(G); 66 | vertex_desc v_sink = boost::add_vertex(G); 67 | vertex_desc v_sink_2 = boost::add_vertex(G); 68 | 69 | unsigned int offset = e + w; 70 | unsigned int max_difficulty = 1e4; 71 | 72 | // Start 73 | adder.add_edge(v_source,v_source_2,p - e*l,0); 74 | for(int i = 0; i < e;i++) adder.add_edge(v_source,i,l,0); 75 | for(int i = 0; i < e;i++) adder.add_edge(v_source_2,i,INT_MAX,0); 76 | for(int i = 0; i < e;i++) adder.add_edge(v_source_2,i+offset,INT_MAX,0); 77 | 78 | // Middle 79 | for(int i = 0; i < m;i++) adder.add_edge(matches[i].u, e + matches[i].v, 1, matches[i].r); 80 | for(int i = m; i < m+d;i++) adder.add_edge(offset + matches[i].u, offset + e + matches[i].v, 1, matches[i].r); 81 | for(int i = e; i < e + w;i++) adder.add_edge(i, offset + i, INT_MAX, 0); 82 | 83 | // End 84 | for(int i = e; i < e + w;i++) adder.add_edge(i,v_sink,l,0); 85 | for(int i = e; i < e + w;i++) adder.add_edge(offset + i,v_sink_2,INT_MAX,0); 86 | 87 | adder.add_edge(v_sink_2,v_sink,p - w*l,0); 88 | 89 | int flow = boost::push_relabel_max_flow(G, v_source, v_sink); 90 | if(flow != p || p < l*max(e,w)) { 91 | cout << "No schedule!" << "\n"; 92 | } else { 93 | boost::successive_shortest_path_nonnegative_weights(G, v_source, v_sink); 94 | int cost = boost::find_flow_cost(G); 95 | cout << cost << "\n"; 96 | } 97 | 98 | return; 99 | } 100 | 101 | int main() { 102 | 103 | ios_base::sync_with_stdio(false); 104 | cin.tie(0); 105 | 106 | int t; 107 | cin >> t; 108 | 109 | while(t--) 110 | solve(); 111 | 112 | return 0; 113 | } 114 | -------------------------------------------------------------------------------- /problems-of-the-week/Motorcycles.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | typedef CGAL::Exact_predicates_exact_constructions_kernel K; 10 | typedef CGAL::Ray_2 Ray; 11 | typedef CGAL::Point_2 Point; 12 | typedef CGAL::Line_2 Line; 13 | 14 | using namespace std; 15 | 16 | typedef struct Biker { 17 | Ray r; 18 | Line l; 19 | int index; 20 | long int y0; 21 | } Biker; 22 | 23 | 24 | void solve() { 25 | 26 | int n; 27 | cin >> n; 28 | 29 | vector motos(0); 30 | 31 | for(int i = 0; i < n;i++) { 32 | long y0,x1,y1; 33 | cin >> y0 >> x1 >> y1; 34 | Line l; 35 | if(y0 < y1) { 36 | l = Line(Point(0,y0),Point(x1,y1)); 37 | } 38 | else { 39 | l = Line(Point(0,-y0),Point(x1,-y1)); 40 | } 41 | Ray r = Ray(Point(0,y0),Point(x1,y1)); 42 | motos.push_back({r,l,i,y0}); 43 | } 44 | 45 | sort(motos.begin(),motos.end(),[](const Biker &b1, const Biker &b2) -> bool { 46 | return b1.y0 > b2.y0; 47 | }); 48 | 49 | vector sol(n,true); 50 | 51 | for(int i = 1; i < n;i++) { 52 | 53 | for(int j = i-1; j >= 0;j--) { 54 | if(!sol[motos[j].index]) { 55 | continue; 56 | } 57 | if(!CGAL::do_intersect(motos[i].r,motos[j].r)){ 58 | break; 59 | } 60 | 61 | auto result = CGAL::compare_slope(motos[i].l, motos[j].l); 62 | if (result == CGAL::Comparison_result::LARGER) { 63 | sol[motos[i].index] = false; 64 | break; 65 | } 66 | else { 67 | sol[motos[j].index] = false; 68 | } 69 | } 70 | } 71 | 72 | for(int i = 0; i < sol.size();i++) { 73 | if(sol[i]) 74 | cout << i << " "; 75 | } 76 | cout << "\n"; 77 | 78 | return; 79 | } 80 | 81 | signed main() { 82 | ios_base::sync_with_stdio(false); 83 | cin.tie(0); 84 | 85 | int t; 86 | cin >> t; 87 | 88 | while(t--) 89 | solve(); 90 | 91 | return 0; 92 | } 93 | -------------------------------------------------------------------------------- /problems-of-the-week/Octopussy.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | void solve() { 6 | int n; cin >> n; 7 | 8 | vector t(n); 9 | for(int i = 0; i < n;i++) 10 | cin >> t[i]; 11 | 12 | for(int i = 1; i < n;i++) { 13 | int parent = (i - 1) / 2; 14 | t[i] = min(t[i],t[parent]-1); 15 | } 16 | 17 | sort(t.begin(),t.end()); 18 | 19 | for(int i = 0; i < n;i++) { 20 | if(t[i] <= i) { 21 | cout << "no" << "\n"; 22 | return; 23 | } 24 | } 25 | 26 | cout << "yes" << "\n"; 27 | return; 28 | } 29 | 30 | signed main() { 31 | 32 | int t; 33 | cin >> t; 34 | 35 | while(t--) 36 | solve(); 37 | 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /problems-of-the-week/Rubeus Hagrid.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define int long 4 | 5 | using namespace std; 6 | 7 | struct Edge { 8 | int to; 9 | int time; 10 | }; 11 | 12 | struct Vertex { 13 | int t; 14 | int s; 15 | }; 16 | 17 | vector g; 18 | vector> graph; 19 | vector ver; 20 | 21 | int totalValue; 22 | int timeSpent; 23 | 24 | void traverse(int idx) { 25 | ver[idx].t = 0; 26 | ver[idx].s = 1; 27 | 28 | for(Edge e : graph[idx]) { 29 | traverse(e.to); 30 | ver[idx].t += 2*e.time + ver[e.to].t; 31 | ver[idx].s += ver[e.to].s; 32 | } 33 | 34 | sort(graph[idx].begin(),graph[idx].end(),[](const Edge &e1, const Edge &e2) -> bool { 35 | int lost1 = ver[e1.to].s * (ver[e2.to].t + 2*e2.time); 36 | int lost2 = ver[e2.to].s * (ver[e1.to].t + 2*e1.time); 37 | return lost2 < lost1; 38 | }); 39 | } 40 | 41 | void traverse2(int idx) { 42 | totalValue -= timeSpent; 43 | 44 | for(Edge e : graph[idx]) { 45 | timeSpent += e.time; 46 | traverse2(e.to); 47 | timeSpent += e.time; 48 | } 49 | } 50 | 51 | 52 | void solve() { 53 | int n; cin >> n; 54 | 55 | g = vector(n+1,0l); 56 | for(int i = 1; i <= n;i++) cin >> g[i]; 57 | 58 | graph = vector>(n+1,vector(0)); 59 | for(int i = 0; i < n;i++) { 60 | int u,v,l; 61 | cin >> u >> v >> l; 62 | graph[u].push_back({v,l}); 63 | } 64 | 65 | ver = vector(n+1); 66 | 67 | timeSpent = 0; 68 | totalValue = accumulate(g.begin(),g.end(),0l); 69 | 70 | traverse(0); 71 | traverse2(0); 72 | 73 | cout << totalValue << "\n"; 74 | } 75 | 76 | signed main() { 77 | ios_base::sync_with_stdio(false); 78 | cin.tie(0); 79 | 80 | int t; cin >> t; 81 | 82 | while(t--) 83 | solve(); 84 | } 85 | -------------------------------------------------------------------------------- /problems-of-the-week/San Francisco.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define int long long 7 | 8 | using namespace std; 9 | 10 | void solve() { 11 | 12 | int n,m,x,k; 13 | cin >> n >> m >> x >> k; 14 | 15 | vector>> graph = vector>>(n,vector>(0)); 16 | vector hasOutgoing = vector(n,false); 17 | 18 | for(int i = 0; i < m;i++) { 19 | int from,to,reward; 20 | cin >> from >> to >> reward; 21 | graph[to].push_back(make_pair(from,reward)); 22 | hasOutgoing[from] = true; 23 | } 24 | 25 | vector> dp = vector>(k+1,vector(n,LLONG_MIN)); 26 | dp[0][0] = 0; 27 | 28 | for(int step = 1; step <= k;step++) { 29 | 30 | for(int i = 1; i < n;i++) { 31 | for(auto transition : graph[i]) { 32 | int from = transition.first; 33 | int reward = transition.second; 34 | dp[step][i] = max(dp[step][i],dp[step-1][from] + reward); 35 | } 36 | 37 | if(dp[step][i] >= x) { 38 | cout << step << "\n"; 39 | return; 40 | } 41 | } 42 | 43 | for(int i = 1; i < n;i++) { 44 | if(!hasOutgoing[i]) { 45 | dp[step][0] = max(dp[step][0],dp[step][i]); 46 | } 47 | } 48 | } 49 | 50 | cout << "Impossible" << "\n"; 51 | 52 | return; 53 | } 54 | 55 | signed main() { 56 | 57 | ios_base::sync_with_stdio(false); 58 | cin.tie(NULL); 59 | 60 | int t; 61 | cin >> t; 62 | 63 | while(t--) 64 | solve(); 65 | 66 | return 0; 67 | } 68 | -------------------------------------------------------------------------------- /problems-of-the-week/Strikesback.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define int long 10 | 11 | using namespace std; 12 | 13 | typedef CGAL::Exact_predicates_inexact_constructions_kernel K; 14 | typedef CGAL::Delaunay_triangulation_2 Triangulation; 15 | typedef CGAL::Point_2 Point; 16 | 17 | typedef CGAL::Gmpq IT; 18 | typedef CGAL::Gmpq ET; 19 | 20 | typedef CGAL::Quadratic_program Program; 21 | typedef CGAL::Quadratic_program_solution Solution; 22 | 23 | struct Positions { 24 | Point p; 25 | double max_dist; 26 | }; 27 | 28 | struct Asteroid { 29 | Point p; 30 | int d; 31 | }; 32 | 33 | void solve() { 34 | int a,s,b; 35 | long e; 36 | cin >> a >> s >> b; 37 | cin >> e; 38 | 39 | vector asteroids = vector(a); 40 | vector positions = vector(s); 41 | vector hunters = vector(b); 42 | 43 | for(int i = 0; i < a; i++) { 44 | int x,y,d; 45 | cin >> x >> y >> d; 46 | asteroids[i] = Asteroid{Point(x,y),d}; 47 | } 48 | 49 | for(int i = 0; i < s; i++) { 50 | int x,y; 51 | cin >> x >> y; 52 | positions[i] = {Point(x,y),DBL_MAX}; 53 | } 54 | 55 | for(int i = 0; i < b; i++) { 56 | int x,y; 57 | cin >> x >> y; 58 | hunters[i] = Point(x,y); 59 | } 60 | 61 | Triangulation t; 62 | t.insert(hunters.begin(), hunters.end()); 63 | 64 | if(b > 0) { 65 | for(int i = 0; i < s;i++) { 66 | Point tmp = t.nearest_vertex(positions[i].p)->point(); 67 | positions[i].max_dist = squared_distance(tmp,positions[i].p); 68 | } 69 | } 70 | 71 | Program lp(CGAL::SMALLER, true, 0, false); 72 | 73 | for(int i = 0; i < a;i++) { 74 | for(int j = 0; j < s;j++) { 75 | if(positions[j].max_dist >= CGAL::squared_distance(positions[j].p, asteroids[i].p)) { 76 | lp.set_a(j,i,-CGAL::Gmpq(1, max(K::FT(1), CGAL::squared_distance(positions[j].p, asteroids[i].p)))); 77 | } 78 | } 79 | lp.set_b(i,-asteroids[i].d); 80 | } 81 | 82 | for(int j = 0; j < s;j++) { 83 | lp.set_a(j,a,1); 84 | } 85 | lp.set_b(a,e); 86 | 87 | Solution solution = CGAL::solve_linear_program(lp, ET()); 88 | if (solution.is_infeasible()) { 89 | cout << "n" << "\n"; 90 | } else { 91 | cout << "y" << "\n"; 92 | } 93 | } 94 | 95 | signed main() { 96 | ios_base::sync_with_stdio(false); 97 | cin.tie(0); 98 | 99 | int t; 100 | cin >> t; 101 | 102 | while(t--) 103 | solve(); 104 | } 105 | -------------------------------------------------------------------------------- /problems-of-the-week/Tracking.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | typedef boost::adjacency_list > graph; 7 | 8 | using namespace std; 9 | 10 | int dijkstra_dist(const graph &G, int s, int t) { 11 | int n = boost::num_vertices(G); 12 | std::vector dist_map(n); 13 | 14 | boost::dijkstra_shortest_paths(G, s, 15 | boost::distance_map(boost::make_iterator_property_map( 16 | dist_map.begin(), boost::get(boost::vertex_index, G)))); 17 | 18 | return dist_map[t]; 19 | } 20 | 21 | 22 | void solve() { 23 | int n,m,k,x,y; 24 | cin >> n >> m >> k >> x >> y; 25 | 26 | graph G(n*(k+1)); 27 | 28 | for(int i = 0; i < m;i++) { 29 | int a,b,c,d; 30 | cin >> a >> b >> c >> d; 31 | 32 | for(int j = 0; j <= k; j++) { 33 | boost::add_edge(j*n+a ,min(j+d,k)*n + b,c,G); 34 | boost::add_edge(j*n+b ,min(j+d,k)*n + a,c,G); 35 | } 36 | } 37 | 38 | cout << dijkstra_dist(G,x,k*n + y) << "\n"; 39 | } 40 | 41 | signed main() { 42 | ios_base::sync_with_stdio(false); 43 | cin.tie(0); 44 | 45 | int t; 46 | cin >> t; 47 | 48 | while(t--) 49 | solve(); 50 | } 51 | -------------------------------------------------------------------------------- /problems/algocoön group.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/algocoön group.pdf -------------------------------------------------------------------------------- /problems/ant challenge.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/ant challenge.pdf -------------------------------------------------------------------------------- /problems/antenna.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/antenna.pdf -------------------------------------------------------------------------------- /problems/asterix and the chariot race.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/asterix and the chariot race.pdf -------------------------------------------------------------------------------- /problems/asterix in switzerland.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/asterix in switzerland.pdf -------------------------------------------------------------------------------- /problems/asterix_the_gaul.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/asterix_the_gaul.pdf -------------------------------------------------------------------------------- /problems/beach_bars.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/beach_bars.pdf -------------------------------------------------------------------------------- /problems/bistro.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/bistro.pdf -------------------------------------------------------------------------------- /problems/boats.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/boats.pdf -------------------------------------------------------------------------------- /problems/buddy selection.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/buddy selection.pdf -------------------------------------------------------------------------------- /problems/build_the_sum.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/build_the_sum.pdf -------------------------------------------------------------------------------- /problems/burning_coins.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/burning_coins.pdf -------------------------------------------------------------------------------- /problems/car sharing.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/car sharing.pdf -------------------------------------------------------------------------------- /problems/casino royale.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/casino royale.pdf -------------------------------------------------------------------------------- /problems/ceryneian hind.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/ceryneian hind.pdf -------------------------------------------------------------------------------- /problems/clues.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/clues.pdf -------------------------------------------------------------------------------- /problems/coin cossing tournament.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/coin cossing tournament.pdf -------------------------------------------------------------------------------- /problems/deck_of_cards.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/deck_of_cards.pdf -------------------------------------------------------------------------------- /problems/dhl.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/dhl.pdf -------------------------------------------------------------------------------- /problems/diet.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/diet.pdf -------------------------------------------------------------------------------- /problems/dominoes.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/dominoes.pdf -------------------------------------------------------------------------------- /problems/even_matrices.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/even_matrices.pdf -------------------------------------------------------------------------------- /problems/even_pairs.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/even_pairs.pdf -------------------------------------------------------------------------------- /problems/evolution.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/evolution.pdf -------------------------------------------------------------------------------- /problems/first steps with bgl.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/first steps with bgl.pdf -------------------------------------------------------------------------------- /problems/firsthit.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/firsthit.pdf -------------------------------------------------------------------------------- /problems/fleetrace.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/fleetrace.pdf -------------------------------------------------------------------------------- /problems/germs.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/germs.pdf -------------------------------------------------------------------------------- /problems/greyjoy.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/greyjoy.pdf -------------------------------------------------------------------------------- /problems/h1n1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/h1n1.pdf -------------------------------------------------------------------------------- /problems/hands.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/hands.pdf -------------------------------------------------------------------------------- /problems/hiking-maps.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/hiking-maps.pdf -------------------------------------------------------------------------------- /problems/hit.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/hit.pdf -------------------------------------------------------------------------------- /problems/idefix and the mansion of the gods.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/idefix and the mansion of the gods.pdf -------------------------------------------------------------------------------- /problems/important bridges.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/important bridges.pdf -------------------------------------------------------------------------------- /problems/inball.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/inball.pdf -------------------------------------------------------------------------------- /problems/knights.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/knights.pdf -------------------------------------------------------------------------------- /problems/light the stage.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/light the stage.pdf -------------------------------------------------------------------------------- /problems/london.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/london.pdf -------------------------------------------------------------------------------- /problems/lord voldemort.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/lord voldemort.pdf -------------------------------------------------------------------------------- /problems/ludo bagman.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/ludo bagman.pdf -------------------------------------------------------------------------------- /problems/marathon.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/marathon.pdf -------------------------------------------------------------------------------- /problems/motorcycles.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/motorcycles.pdf -------------------------------------------------------------------------------- /problems/moving_books.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/moving_books.pdf -------------------------------------------------------------------------------- /problems/nemean lion.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/nemean lion.pdf -------------------------------------------------------------------------------- /problems/new york.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/new york.pdf -------------------------------------------------------------------------------- /problems/octopussy.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/octopussy.pdf -------------------------------------------------------------------------------- /problems/placing knights.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/placing knights.pdf -------------------------------------------------------------------------------- /problems/real estate market.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/real estate market.pdf -------------------------------------------------------------------------------- /problems/revenge of the sith.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/revenge of the sith.pdf -------------------------------------------------------------------------------- /problems/rubeus_hagrid.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/rubeus_hagrid.pdf -------------------------------------------------------------------------------- /problems/san_francisco.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/san_francisco.pdf -------------------------------------------------------------------------------- /problems/search_snippets.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/search_snippets.pdf -------------------------------------------------------------------------------- /problems/severus_snape.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/severus_snape.pdf -------------------------------------------------------------------------------- /problems/shopping trip.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/shopping trip.pdf -------------------------------------------------------------------------------- /problems/strikesback.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/strikesback.pdf -------------------------------------------------------------------------------- /problems/suez.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/suez.pdf -------------------------------------------------------------------------------- /problems/the augean stables.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/the augean stables.pdf -------------------------------------------------------------------------------- /problems/the fighting pits of meereen .pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/the fighting pits of meereen .pdf -------------------------------------------------------------------------------- /problems/the_great_game.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/the_great_game.pdf -------------------------------------------------------------------------------- /problems/tiles.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/tiles.pdf -------------------------------------------------------------------------------- /problems/tracking.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/tracking.pdf -------------------------------------------------------------------------------- /problems/what is the maximum.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/what is the maximum.pdf -------------------------------------------------------------------------------- /problems/world cup.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/francois141/algo-lab/8c5980fc979bb496b69565b18432dfc30198b408/problems/world cup.pdf -------------------------------------------------------------------------------- /resume/README.md: -------------------------------------------------------------------------------- 1 | # ALGO Lab ETHZ 2022 2 | 3 | ## STL 4 | 5 | #### Sort an array 6 | 7 | ```c++ 8 | sort(array.begin(),array.end(), [](const int &e1, const int &e2) -> bool { 9 | return e1 < e2; 10 | }); 11 | ``` 12 | 13 | #### Sum of all elements in an array 14 | 15 | ```c++ 16 | int sum = accumulate(array.begin(),array.end(),0); 17 | ``` 18 | 19 | #### Prefix sum with stl 20 | 21 | ```c++ 22 | partial_sum(array.begin(),array.end(),array.begin()); 23 | ``` 24 | 25 | #### Shuffles all values in an array (avoid adversary input) 26 | 27 | ```c++ 28 | random_shuffle(array.begin(),array.end()); 29 | ``` 30 | 31 | #### Check if an elements is in array (must be sorted) 32 | 33 | ```c++ 34 | bool present = binary_search(array.begin(),array.end(), element); 35 | ``` 36 | 37 | #### Find first element bigger equal value (must be sorted) 38 | 39 | This return an iterator. We use * to dereference the iterator. 40 | 41 | ```c++ 42 | int returned_value = *min_value(array.begin(),array.end(),value); 43 | ``` 44 | 45 | #### Find first element bigger than value (must be sorted) 46 | 47 | This return an iterator. We use * to dereference the iterator. 48 | 49 | ```c++ 50 | int returned_value = *max_value(array.begin(),array.end(),value); 51 | ``` 52 | 53 | #### Intersection of two sets 54 | 55 | ```c++ 56 | std::vector v_intersection; 57 | std::set_intersection(array1.begin(), array1.end(), array2.begin(), array2.end(), std::back_inserter(v_intersection)); 58 | ``` 59 | 60 | #### Union of two sets 61 | 62 | ```c++ 63 | std::vector v_union; 64 | std::set_union(array1.begin(), array1.end(), array2.begin(), array2.end(), std::back_inserter(v_union)); 65 | ``` 66 | ## Boost 67 | 68 | ### Basics 69 | 70 | #### Declaration of graphs 71 | 72 | ```cpp 73 | #include 74 | 75 | // Create undirected graph 76 | typedef boost::adjacency_list graph; 77 | 78 | // Create directed graph 79 | typedef boost::adjacency_list graph; 80 | 81 | // Create directed weighted graph 82 | typedef boost::adjacency_list > weighted_graph; 83 | ``` 84 | 85 | #### Manipulation of edges with propery map 86 | ```cpp 87 | // Graph 88 | typedef boost::adjacency_list> graph; 89 | 90 | // Iterator over descriptor 91 | typedef boost::graph_traits::edge_iterator edge_it; 92 | 93 | // Descriptor 94 | typedef boost::graph_traits::edge_descriptor edge_descriptor; 95 | 96 | // Edge weight 97 | typedef boost::property_map::type edge_weights_map; 98 | 99 | // Retrieve the property map 100 | edge_weights_map edge_map = get(boost::edge_weight,G); 101 | 102 | edge_it e_beg, e_end; 103 | for (boost::tie(e_beg, e_end) = boost::edges(G); e_beg != e_end; ++e_beg) { 104 | // Output from & to 105 | std::cout << boost::source(*e_beg, G) << " " << boost::target(*e_beg, G) << "\n"; 106 | // Output weight of the edge 107 | std::cout << edge_map[*e_beg] << "\n"; 108 | } 109 | 110 | ``` 111 | 112 | #### Iterator over all edges from a single vertex 113 | 114 | ```cpp 115 | // Graph 116 | typedef boost::adjacency_list> graph; 117 | 118 | // Iterator over descriptor 119 | typedef boost::graph_traits::out_edge_iterator out_edge_it; 120 | 121 | out_edge_it e_beg, e_end; 122 | for (boost::tie(e_beg, e_end) = boost::out_edges(G); e_beg != e_end; ++e_beg) { 123 | std::cout << boost::target(*e_beg, G) << "\n"; 124 | 125 | } 126 | ``` 127 | 128 | ### Algorithms 129 | 130 | #### Dijkstra - shortest path from one node to all other in the graph 131 | 132 | ```cpp 133 | 134 | #include 135 | 136 | std::vector dijkstra_dist(const weighted_graph &G, int s, int t) { 137 | int n = boost::num_vertices(G); 138 | std::vector dist_map(n); 139 | 140 | boost::dijkstra_shortest_paths(G, s,boost::distance_map(boost::make_iterator_property_map(dist_map.begin(),boost::get(boost::vertex_index, G)))); 141 | 142 | return dist_map; 143 | } 144 | 145 | ``` 146 | 147 | #### MST - Kruskal algorithm 148 | 149 | ```cpp 150 | 151 | #include 152 | 153 | vector kruskal(const weighted_graph &G) { 154 | std::vector mst; 155 | 156 | boost::kruskal_minimum_spanning_tree(G, std::back_inserter(mst)); 157 | 158 | return mst; 159 | } 160 | ``` 161 | 162 | 163 | #### Maximum matching 164 | 165 | ```cpp 166 | 167 | #include 168 | 169 | int maximum_matching(const graph &G) { 170 | int n = boost::num_vertices(G); 171 | std::vector mate_map(n); 172 | 173 | const vertex_desc NULL_VERTEX = boost::graph_traits::null_vertex(); 174 | 175 | boost::edmonds_maximum_cardinality_matching(G, boost::make_iterator_property_map(mate_map.begin(), boost::get(boost::vertex_index, G))); 176 | int matching_size = boost::matching_size(G, boost::make_iterator_property_map(mate_map.begin(), boost::get(boost::vertex_index, G))); 177 | 178 | return matching_size; 179 | } 180 | 181 | ``` 182 | 183 | #### Bipartitness of a graph 184 | 185 | ```cpp 186 | bool is_bipartite = boost::is_bipartite(G); 187 | ``` 188 | 189 | #### Connected components 190 | 191 | ```cpp 192 | 193 | #include 194 | 195 | void strong_connected_comp(const graph &G) { 196 | int n = boost::num_vertices(G); 197 | 198 | std::vector scc_map(n); 199 | int nscc = boost::connected_components(G,boost::make_iterator_property_map(scc_map.begin(), boost::get(boost::vertex_index, G))); 200 | 201 | std::cout << "Number of connected components: " << nscc << "\n"; 202 | for (int i = 0; i < n; ++i) { 203 | std::cout << i << " " << scc_map[i] << "\n"; 204 | } 205 | } 206 | ``` 207 | 208 | 209 | #### Strongly connected components 210 | 211 | ```cpp 212 | 213 | #include 214 | 215 | void strong_connected_comp(const graph &G) { 216 | int n = boost::num_vertices(G); 217 | 218 | std::vector scc_map(n); 219 | int nscc = boost::strong_components(G,boost::make_iterator_property_map(scc_map.begin(), boost::get(boost::vertex_index, G))); 220 | 221 | std::cout << "Number of connected components: " << nscc << "\n"; 222 | for (int i = 0; i < n; ++i) { 223 | std::cout << i << " " << scc_map[i] << "\n"; 224 | } 225 | } 226 | ``` 227 | 228 | ## CGAL 229 | 230 | ### Basics 231 | 232 | #### Kernels 233 | 234 | ```cpp 235 | typedef CGAL::Exact_predicates_inexact_constructions_kernel K; 236 | typedef CGAL::Exact_predicates_exact_constructions_kernel K; 237 | typedef CGAL::Exact_predicates_exact_constructions_kernel_with_sqrt K; 238 | ``` 239 | 240 | #### Basics types 241 | 242 | ```cpp 243 | typedef K::Point_2 Point; 244 | typedef K::Line_2 Line; 245 | typedef K::Ray_2 Ray; 246 | typedef K::Triangle_2 Triangle; 247 | typedef K::Circle_2 Circle; 248 | typedef K::FT FT; 249 | 250 | Point point = Point(x,y); 251 | Line line = Line(p1, p2); 252 | Ray ray = Ray(start_point, direction); 253 | Triangle triangle = Triangle(p1,p2,p3); 254 | Circle circle = Circle(c1,c2,c3); 255 | 256 | ``` 257 | 258 | #### Ceil & floor 259 | 260 | ```cpp 261 | double floor_to_double(const K::FT& x) 262 | { 263 | double a = std::floor(CGAL::to_double(x)); 264 | while (a > x) a -= 1; 265 | while (a+1 <= x) a += 1; 266 | return a; 267 | } 268 | 269 | double ceil_to_double(const K::FT& x) 270 | { 271 | double a = std::ceil(CGAL::to_double(x)); 272 | while (a > x) a -= 1; 273 | while (a+1 <= x) a += 1; 274 | return a; 275 | } 276 | ``` 277 | 278 | ### Algorithms 279 | 280 | #### Intersections & distance 281 | 282 | ```cpp 283 | 284 | // Check for intersection 285 | if (CGAL::do_intersect(s[i],s[j])) { 286 | // Compute intersection 287 | auto o = CGAL::intersection(s[i],s[j]); 288 | if (const Point* op = boost::get(&*o)) 289 | std::cout << "point: " << *op << "\n"; 290 | else if (const Segment* os = boost::get(&*o)) 291 | std::cout << "segment: " << os->source() << " " << os->target() << "\n"; 292 | else 293 | throw std::runtime_error("strange segment intersection"); 294 | } 295 | 296 | // Get distance between two points 297 | auto distance = CGAL::squared_distance(p1,p2); 298 | ``` 299 | 300 | #### Get minimum enclosing cercle 301 | 302 | ```cpp 303 | 304 | #include 305 | #include 306 | 307 | typedef CGAL::Min_circle_2_traits_2 Traits; 308 | typedef CGAL::Min_circle_2 Min_circle; 309 | 310 | Min_circle mc(Points.begin(), Points.end(), true); 311 | 312 | Traits::Circle c = mc.circle(); 313 | std::cout << c.center() << " " << c.squared_radius() << "\n"; 314 | ``` 315 | 316 | ### Triangulation 317 | 318 | ### Definitions 319 | 320 | #### Basic triangulation with no information 321 | 322 | ```cpp 323 | #include 324 | #include 325 | 326 | // Definitions 327 | typedef CGAL::Exact_predicates_inexact_constructions_kernel K; 328 | typedef CGAL::Delaunay_triangulation_2 Triangulation; 329 | 330 | // Triangulation object 331 | Triangulation t; 332 | // Insert points 333 | t.insert(points.begin(),points.end()); 334 | ``` 335 | 336 | #### Basic triangulation with vertex information 337 | 338 | ```cpp 339 | #include 340 | #include 341 | // Also include this file 342 | #include 343 | 344 | // Definitions 345 | typedef CGAL::Exact_predicates_inexact_constructions_kernel K; 346 | typedef CGAL::Triangulation_vertex_base_with_info_2 Vb; 347 | typedef CGAL::Triangulation_face_base_2 Fb; 348 | typedef CGAL::Triangulation_data_structure_2 Tds; 349 | typedef CGAL::Delaunay_triangulation_2 Triangulation; 350 | 351 | typedef K::Point_2 Point; 352 | 353 | vector> points; 354 | 355 | // Triangulation object 356 | Triangulation t; 357 | // Insert points 358 | t.insert(points.begin(),points.end()); 359 | ``` 360 | 361 | #### Iterate over faces, edges & vertices 362 | 363 | ```cpp 364 | typedef Triangulation::Finite_faces_iterator Face_iterator; 365 | typedef Triangulation::Finite_edges_iterator Edte_iterator; 366 | typedef Triangulation::Finite_vertices_iterator Vertex_iterator; 367 | 368 | for (Face_iterator f = t.finite_faces_begin(); f != t.finite_faces_end(); ++f) { 369 | std::cout << t.triangle(f) << endl; 370 | } 371 | 372 | for (Edge_iterator e = t.finite_edges_begin(); e != t.finite_edges_end(); ++e) { 373 | std::cout << t.segment(e) << endl; 374 | 375 | // Get edge length 376 | auto length = t.segment(e).squared_length(); 377 | 378 | // Get vertices 379 | Triangulation::Vertex_handle v1 = e->first->vertex((e->second + 1) % 3); 380 | Triangulation::Vertex_handle v2 = e->first->vertex((e->second + 2) % 3); 381 | 382 | // Print point 383 | std::cout << "e = " << v1->point() << " <-> " << v2->point() << std::endl; 384 | 385 | // Print informations 386 | std::cout << "i = " << v1->info() << " <-> " << v2->info() << std::endl; 387 | } 388 | 389 | for (Vertex_iterator v = t.finite_vertices_begin(); e != t.finite_vertices_end(); ++e) { 390 | std::cout << v->point() << " " v->info() << endl; 391 | } 392 | ``` 393 | 394 | #### Incident edges from a vertex 395 | 396 | 397 | ```cpp 398 | Triangulation::Vertex_handle v = handle; 399 | 400 | Triangulation::Edge_circulator c = t.incident_edges(v); 401 | do { 402 | if (t.is_infinite(c)) { ... } 403 | // Do something with the edges here 404 | } while (++c != t.incident_edges(v)); 405 | ``` 406 | -------------------------------------------------------------------------------- /week1/Build the Sum.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | void solve() { 8 | 9 | int n; 10 | cin >> n; 11 | 12 | vector a(n); 13 | 14 | for(int i = 0; i < n;i++) { 15 | cin >> a[i]; 16 | } 17 | 18 | cout << accumulate(a.begin(),a.end(),0) << "\n"; 19 | } 20 | 21 | int main() { 22 | 23 | int t; 24 | cin >> t; 25 | 26 | while(t--) 27 | solve(); 28 | 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /week1/Dominoes.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | void solve() { 7 | 8 | int n; 9 | cin >> n; 10 | 11 | vector a(n); 12 | for(int i = 0; i < n;i++) { 13 | cin >> a[i]; 14 | } 15 | 16 | int position = 0; 17 | int until = 1; 18 | 19 | while(position < n && position < until) { 20 | until = max(until,position + a[position]); 21 | position++; 22 | } 23 | 24 | cout << min(position,n) << "\n"; 25 | 26 | return; 27 | } 28 | 29 | 30 | int main() { 31 | 32 | int t; 33 | cin >> t; 34 | 35 | while(t--) 36 | solve(); 37 | 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /week1/Even Matrices.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | void solve() { 7 | 8 | int n; 9 | cin >> n; 10 | n++; 11 | 12 | vector> matrix = vector>(n,vector(n,0)); 13 | 14 | for(int i = 1; i < n;i++) { 15 | for(int j = 1; j < n;j++) { 16 | cin >> matrix[i][j]; 17 | matrix[i][j] += matrix[i-1][j] + matrix[i][j-1] - matrix[i-1][j-1]; 18 | } 19 | } 20 | 21 | unsigned int count = 0; 22 | 23 | for(int i = 0; i < n; i++) { 24 | for(int j = 0; j < i; j++) { 25 | unsigned int evens = 0; 26 | unsigned int odds = 0; 27 | for(int k = 0; k < n; k++) { 28 | (matrix[i][k]-matrix[j][k]) % 2 == 0 ? evens++ : odds++; 29 | } 30 | count += (evens*(evens-1) + odds*(odds-1)) / 2; 31 | } 32 | } 33 | 34 | cout << count << "\n"; 35 | } 36 | 37 | int main() { 38 | 39 | int t; 40 | cin >> t; 41 | 42 | while(t--) { 43 | solve(); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /week1/Even Pairs.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | 9 | void solve() { 10 | 11 | int n; 12 | cin >> n; 13 | 14 | vector a(n); 15 | 16 | for(int i = 0; i < n;i++) { 17 | cin >> a[i]; 18 | } 19 | 20 | partial_sum(a.begin(), a.end(), a.begin(),plus()); 21 | 22 | int evens = count_if(a.begin(), a.end(),[](int x) -> int { 23 | return x % 2 == 0; 24 | }); 25 | 26 | int odds = count_if(a.begin(), a.end(),[](int x) -> int { 27 | return x % 2 == 1; 28 | }); 29 | 30 | cout << (evens*(evens-1) + odds*(odds-1)) / 2 + evens << "\n"; 31 | 32 | return; 33 | } 34 | 35 | 36 | int main() { 37 | 38 | int t; 39 | cin >> t; 40 | 41 | while(t--) 42 | solve(); 43 | 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /week10/Clues.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | typedef CGAL::Exact_predicates_inexact_constructions_kernel K; 15 | 16 | typedef int 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 Triangulation; 21 | typedef CGAL::Point_2 Point; 22 | 23 | typedef Triangulation::Finite_faces_iterator Face_iterator; 24 | 25 | typedef boost::adjacency_list graph; 26 | 27 | using namespace std; 28 | 29 | #define int long 30 | 31 | void solve() { 32 | 33 | int n,m,r; 34 | cin >> n >> m >> r; 35 | 36 | vector> radios(0); 37 | vector> clues(0); 38 | 39 | for(int i = 0; i < n;i++) { 40 | int x,y; 41 | cin >> x >> y; 42 | radios.push_back(make_pair(Point(x,y),i)); 43 | } 44 | 45 | sort(radios.begin(),radios.end(), [](auto r1, auto r2) { 46 | return r1.first.x() < r2.first.x(); 47 | }); 48 | 49 | for(int i = 0; i < m;i++) { 50 | int x,y,z,t; 51 | cin >> x >> y >> z >> t; 52 | clues.push_back(make_pair(Point(x,y),Point(z,t))); 53 | } 54 | 55 | graph G(n); 56 | 57 | for(int i = 0; i < n;i++) { 58 | for(int j = i+1; j < n;j++) { 59 | if(radios[j].first.x() - radios[i].first.x() > r) 60 | break; 61 | if(CGAL::squared_distance(radios[i].first,radios[j].first) <= r*r) { 62 | boost::add_edge(i,j,G); 63 | } 64 | } 65 | } 66 | 67 | bool is_bipartite = boost::is_bipartite(G); 68 | 69 | Triangulation t; 70 | t.insert(radios.begin(),radios.end()); 71 | 72 | graph G2(n); 73 | 74 | for(auto e = t.finite_edges_begin(); e != t.finite_edges_end(); ++e) { 75 | Index i1 = e->first->vertex((e->second+1)%3)->info(); 76 | Index i2 = e->first->vertex((e->second+2)%3)->info(); 77 | if(t.segment(e).squared_length() <= r*r) { 78 | boost::add_edge(i1,i2,G2); 79 | } 80 | } 81 | 82 | vectorcomponent(num_vertices(G2)); 83 | boost::connected_components(G2, &component[0]); 84 | 85 | for(int i = 0; i < m;i++) { 86 | 87 | auto p1 = clues[i].first; 88 | auto p2 = clues[i].second; 89 | 90 | if(!is_bipartite) { 91 | cout << "n"; 92 | continue; 93 | } 94 | 95 | if(CGAL::squared_distance(p1,p2) <= r*r) { 96 | cout << "y"; 97 | continue; 98 | } 99 | 100 | auto n1 = t.nearest_vertex(p1); 101 | auto n2 = t.nearest_vertex(p2); 102 | 103 | if(CGAL::squared_distance(p1,n1->point()) > r*r || CGAL::squared_distance(p2,n2->point()) > r*r) { 104 | cout << "n"; 105 | continue; 106 | } 107 | 108 | if(component[n1->info()] == component[n2->info()]) { 109 | cout << "y"; 110 | } 111 | else { 112 | cout << "n"; 113 | } 114 | } 115 | cout << "\n"; 116 | } 117 | 118 | 119 | signed main() { 120 | int t; cin >> t; 121 | 122 | while(t--) { 123 | solve(); 124 | } 125 | return 0; 126 | } 127 | -------------------------------------------------------------------------------- /week10/DHL.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define int long 4 | 5 | using namespace std; 6 | 7 | void solve() { 8 | int n; 9 | cin >> n; 10 | 11 | vector a(n,0); 12 | vector b(n,0); 13 | 14 | for(int i = 0; i < n;i++) cin >> a[i]; 15 | for(int i = 0; i < n;i++) cin >> b[i]; 16 | 17 | vector> dp(n + 1, vector(n + 1, INT_MAX)); 18 | dp[0][0] = 0; 19 | 20 | for (int i = 1; i <= n; i++) { 21 | for (int j = 1; j <= n; j++) { 22 | int pred = min({dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]}); 23 | dp[i][j] = pred + (a[i - 1] - 1) * (b[j - 1] - 1); 24 | } 25 | } 26 | 27 | cout << dp.back().back() << "\n"; 28 | } 29 | 30 | signed main() { 31 | ios_base::sync_with_stdio(false); 32 | cin.tie(0); 33 | 34 | int t; 35 | cin >> t; 36 | 37 | while(t--) 38 | solve(); 39 | } 40 | -------------------------------------------------------------------------------- /week10/Fleetrace.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | typedef boost::adjacency_list_traits traits; 12 | typedef boost::adjacency_list > > > > graph; 17 | 18 | typedef boost::graph_traits::edge_descriptor edge_desc; 19 | typedef boost::graph_traits::out_edge_iterator out_edge_it; 20 | 21 | class edge_adder { 22 | graph &G; 23 | 24 | public: 25 | explicit edge_adder(graph &G) : G(G) {} 26 | void add_edge(int from, int to, long capacity, long cost) { 27 | auto c_map = boost::get(boost::edge_capacity, G); 28 | auto r_map = boost::get(boost::edge_reverse, G); 29 | auto w_map = boost::get(boost::edge_weight, G); // new! 30 | const edge_desc e = boost::add_edge(from, to, G).first; 31 | const edge_desc rev_e = boost::add_edge(to, from, G).first; 32 | c_map[e] = capacity; 33 | c_map[rev_e] = 0; // reverse edge has no capacity! 34 | r_map[e] = rev_e; 35 | r_map[rev_e] = e; 36 | w_map[e] = cost; // new assign cost 37 | w_map[rev_e] = -cost; // new negative cost 38 | } 39 | }; 40 | 41 | void solve() { 42 | 43 | int b,s,p; 44 | cin >> b >> s >> p; 45 | 46 | vector>> pairs(b,vector>(0)); 47 | for(int i = 0; i < p;i++) { 48 | int bi,si,pi; 49 | cin >> bi >> si >> pi; 50 | pairs[bi].push_back(make_pair(si,50-pi)); 51 | } 52 | 53 | graph G(b+s); 54 | 55 | edge_adder adder(G); 56 | 57 | auto v_source = boost::add_vertex(G); 58 | auto v_sink = boost::add_vertex(G); 59 | 60 | for(int i = 0; i < pairs.size();i++) { 61 | for(int j = 0; j < pairs[i].size();j++) { 62 | auto e = pairs[i][j]; 63 | adder.add_edge(i,b+e.first,1,e.second); 64 | } 65 | } 66 | 67 | for(int i = 0; i < b;i++) { 68 | adder.add_edge(v_source,i,1,0); 69 | adder.add_edge(i,v_sink,1,50); 70 | } 71 | for(int i = 0; i < s;i++) { 72 | adder.add_edge(b+i,v_sink,1,0); 73 | } 74 | 75 | boost::successive_shortest_path_nonnegative_weights(G, v_source, v_sink); 76 | int cost = boost::find_flow_cost(G); 77 | 78 | cout << 50*b - cost << "\n"; 79 | } 80 | 81 | int main() { 82 | 83 | ios_base::sync_with_stdio(false); 84 | cin.tie(0); 85 | 86 | int t; cin >> t; 87 | 88 | while(t--) 89 | solve(); 90 | 91 | return 0; 92 | } 93 | -------------------------------------------------------------------------------- /week10/New York.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | vector> graph; 6 | 7 | vector t; 8 | set s; 9 | multiset values; 10 | deque path; 11 | vector p; 12 | 13 | int n,m,k; 14 | 15 | void dfs(int idx) { 16 | 17 | if(path.size() == m) { 18 | 19 | int minT = *values.begin(); 20 | int maxT = *values.rbegin(); 21 | 22 | if(maxT - minT <= k) { 23 | s.insert(path[0]); 24 | } 25 | } 26 | 27 | for(int next : graph[idx]) { 28 | 29 | path.push_back(next); 30 | values.insert(t[next]); 31 | 32 | if(path.size() > m) { 33 | values.erase(values.find(t[path[0]])); 34 | path.pop_front(); 35 | } 36 | 37 | dfs(next); 38 | 39 | if(path[0] != 0) { 40 | int p_idx = p[path[0]]; 41 | path.push_front(p_idx); 42 | values.insert(t[p_idx]); 43 | } 44 | 45 | values.erase(values.find(t[next])); 46 | path.pop_back(); 47 | } 48 | } 49 | 50 | void solve() { 51 | 52 | cin >> n >> m >> k; 53 | 54 | t = vector(n); 55 | for(int i = 0; i < n;i++) cin >> t[i]; 56 | 57 | p = vector(n,0); 58 | graph = vector>(n,vector(0)); 59 | for(int i = 0; i < n-1;i++) { 60 | int from,to; cin >> from >> to; 61 | graph[from].push_back(to); 62 | p[to] = from; 63 | } 64 | 65 | s = set(); 66 | values = multiset(); 67 | 68 | path = deque(0); 69 | path.push_back(0); 70 | values.insert(t[0]); 71 | 72 | dfs(0); 73 | 74 | if(s.empty()) { 75 | cout << "Abort mission"; 76 | } 77 | else { 78 | for(int tmp : s) { 79 | cout << tmp << " "; 80 | } 81 | } 82 | cout << "\n"; 83 | 84 | return; 85 | } 86 | 87 | signed main() { 88 | ios_base::sync_with_stdio(false); 89 | cin.tie(0); 90 | 91 | int t; cin >> t; 92 | 93 | while(t--) 94 | solve(); 95 | 96 | return 0; 97 | } 98 | -------------------------------------------------------------------------------- /week11/Asterix in Switzerland.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | #define int long 11 | 12 | typedef boost::adjacency_list_traits traits; 13 | typedef boost::adjacency_list>>> graph; 17 | 18 | typedef traits::vertex_descriptor vertex_desc; 19 | typedef traits::edge_descriptor edge_desc; 20 | 21 | class edge_adder { 22 | 23 | graph &G; 24 | 25 | public: 26 | explicit edge_adder(graph &G) : G(G) {} 27 | 28 | void add_edge(int from, int to, int weight) { 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] = weight; 34 | c_map[rev_e] = 0; 35 | r_map[e] = rev_e; 36 | r_map[rev_e] = e; 37 | } 38 | }; 39 | 40 | void solve() { 41 | 42 | int n,m; 43 | cin >> n >> m; 44 | 45 | graph G(n); 46 | edge_adder adder(G); 47 | 48 | auto v_source = boost::add_vertex(G); 49 | auto v_sink = boost::add_vertex(G); 50 | 51 | int sum = 0; 52 | 53 | vector b(n); 54 | for(int i = 0; i < n;i++) { 55 | cin >> b[i]; 56 | if(b[i] > 0) { 57 | adder.add_edge(v_source,i,b[i]); 58 | sum += b[i]; 59 | } 60 | else { 61 | adder.add_edge(i,v_sink,-b[i]); 62 | } 63 | } 64 | 65 | for(int i = 0; i < m;i++) { 66 | int from, to, amount; 67 | cin >> from >> to >> amount; 68 | adder.add_edge(from,to,amount); 69 | } 70 | 71 | long flow = boost::push_relabel_max_flow(G, v_source, v_sink); 72 | if(sum - flow > 0) { 73 | cout << "yes" << endl; 74 | } 75 | else { 76 | cout << "no" << endl; 77 | } 78 | 79 | return; 80 | } 81 | 82 | signed main() { 83 | 84 | ios_base::sync_with_stdio(false); 85 | cin.tie(0); 86 | 87 | int t; 88 | cin >> t; 89 | 90 | while(t--) 91 | solve(); 92 | } 93 | -------------------------------------------------------------------------------- /week11/Sith.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | #define int long 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 Triangulation; 17 | 18 | typedef boost::adjacency_list graph; 19 | 20 | typedef CGAL::Point_2 Point; 21 | 22 | using namespace std; 23 | 24 | int n,r; 25 | vector> planets; 26 | 27 | int testSize(int middle) { 28 | Triangulation t; 29 | t.insert(planets.begin() + middle, planets.end()); 30 | 31 | graph G(n - middle); 32 | 33 | for(auto e = t.finite_edges_begin(); e != t.finite_edges_end(); ++e) { 34 | if(t.segment(e).squared_length() <= r*r) { 35 | auto idx1 = e->first->vertex((e->second + 1) % 3)->info() - middle; 36 | auto idx2 = e->first->vertex((e->second + 2) % 3)->info() - middle; 37 | boost::add_edge(idx1,idx2,G); 38 | } 39 | } 40 | 41 | vector component(n-middle); 42 | boost::connected_components(G,&component[0]); 43 | 44 | vector size(n-middle,0); 45 | for(auto c : component) size[c]++; 46 | 47 | return *max_element(size.begin(),size.end()); 48 | } 49 | 50 | void solve() { 51 | cin >> n >> r; 52 | 53 | planets = vector>(n); 54 | for(int i = 0; i < n;i++) { 55 | int x,y; 56 | cin >> x >> y; 57 | planets[i] = make_pair(Point(x,y),i); 58 | } 59 | 60 | int start = 0; 61 | int end = planets.size(); 62 | 63 | while(start != end) { 64 | int middle = (start + end + 1) / 2; 65 | if(testSize(middle) >= middle) { 66 | start = middle; 67 | } else { 68 | end = middle-1; 69 | } 70 | } 71 | 72 | cout << start << "\n"; 73 | } 74 | 75 | signed main(){ 76 | ios_base::sync_with_stdio(false); 77 | cin.tie(0); 78 | 79 | int t; 80 | cin >> t; 81 | 82 | while(t--) 83 | solve(); 84 | } 85 | -------------------------------------------------------------------------------- /week11/The Fighting Pits of Meereen.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define int long 4 | 5 | using namespace std; 6 | 7 | typedef vector VI; 8 | typedef vector VII; 9 | typedef vector VIII; 10 | typedef vector VIIII; 11 | 12 | VIIII dp; 13 | VI f; 14 | int n,k,m; 15 | 16 | struct Q 17 | { 18 | int f1; 19 | int f2; 20 | int f3; 21 | }; 22 | 23 | struct K 24 | { 25 | int q1; 26 | int q2; 27 | int q3; 28 | }; 29 | 30 | K encode(Q &north, Q &south, int diff) { 31 | int q1 = north.f1*5+north.f2; 32 | int q2 = south.f1*5+south.f2; 33 | return {q1,q2,diff+12}; 34 | }; 35 | 36 | Q insert(Q &q, int val) { 37 | return Q{val,q.f1,q.f2}; 38 | }; 39 | 40 | int size(Q &q) { 41 | if(m == 2) 42 | return set({0,q.f1,q.f2}).size() - 1; 43 | return set({0,q.f1,q.f2,q.f3}).size() - 1; 44 | }; 45 | 46 | int excitement(Q &q,int diff) { 47 | return size(q)*1000 - int(pow(2,abs(diff))); 48 | } 49 | 50 | int solve(int idx, Q north, Q south, int diff) { 51 | 52 | if(abs(diff) >= 12) return INT_MIN; 53 | if(idx < 0) return 0; 54 | 55 | K key = encode(north,south,diff); 56 | if(dp[idx][key.q1][key.q2][key.q3] != -1) return dp[idx][key.q1][key.q2][key.q3]; 57 | 58 | Q new_north = insert(north,f[idx]); 59 | Q new_south = insert(south,f[idx]); 60 | 61 | int val_north = excitement(new_north, diff+1); 62 | int val_south = excitement(new_south, diff-1); 63 | 64 | int best = INT_MIN; 65 | if(val_north >= 0) 66 | { 67 | best = max(best,val_north + solve(idx-1, new_north,south,diff+1)); 68 | } 69 | if(val_south >= 0) 70 | { 71 | best = max(best,val_south + solve(idx-1, north,new_south,diff-1)); 72 | } 73 | 74 | return dp[idx][key.q1][key.q2][key.q3] = best; 75 | } 76 | 77 | void solve() { 78 | 79 | cin >> n >> k >> m; 80 | 81 | f = VI(n); 82 | for(int i = n-1; i >= 0;i--) { 83 | cin >> f[i]; 84 | f[i]++; 85 | } 86 | 87 | dp = VIIII(n, VIII(25,VII(25,VI(25,-1)))); 88 | 89 | Q init_empty = {0,0,0}; 90 | cout << solve(n-1,init_empty,init_empty, 0) << endl; 91 | } 92 | 93 | int main() { 94 | 95 | ios_base::sync_with_stdio(false); 96 | cin.tie(0); 97 | 98 | int t; 99 | cin >> t; 100 | 101 | while(t--) 102 | solve(); 103 | 104 | return 0; 105 | } 106 | -------------------------------------------------------------------------------- /week11/Worldcup.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | #define int long 11 | 12 | typedef int IT; 13 | typedef CGAL::Gmpz ET; 14 | 15 | typedef CGAL::Quadratic_program Program; 16 | typedef CGAL::Quadratic_program_solution Solution; 17 | 18 | typedef CGAL::Exact_predicates_inexact_constructions_kernel K; 19 | typedef CGAL::Delaunay_triangulation_2 Triangulation; 20 | typedef CGAL::Point_2 Point; 21 | 22 | using namespace std; 23 | 24 | int floor_to_long(const CGAL::Quotient& x) 25 | { 26 | double a = std::floor(CGAL::to_double(x)); 27 | while (a > x) a -= 1; 28 | while (a+1 <= x) a += 1; 29 | return a; 30 | } 31 | 32 | struct Warehouse { 33 | Point p; 34 | int supply; 35 | int alcohol; 36 | }; 37 | 38 | struct Stadium { 39 | Point p; 40 | int demand; 41 | int upper; 42 | }; 43 | 44 | void solve() { 45 | int n,m,c; 46 | cin >> n >> m >> c; 47 | 48 | vector points(0); 49 | 50 | vector warehouses(n); 51 | for(int i = 0; i < n;i++) { 52 | int x,y,s,a; 53 | cin >> x >> y >> s >> a; 54 | warehouses[i] = {Point(x,y),s,a}; 55 | points.push_back(Point(x,y)); 56 | } 57 | 58 | vector stadiums(m); 59 | for(int j = 0; j < m;j++) { 60 | int x,y,d,u; 61 | cin >> x >> y >> d >> u; 62 | stadiums[j] = {Point(x,y),d,100*u}; 63 | points.push_back(Point(x,y)); 64 | } 65 | 66 | vector> revenues(n,vector(m)); 67 | for(int i = 0; i < n;i++) { 68 | for(int j = 0; j < m;j++) { 69 | cin >> revenues[i][j]; 70 | } 71 | } 72 | 73 | Triangulation t; 74 | t.insert(points.begin(),points.end()); 75 | 76 | vector> contours(0); 77 | for(int k = 0; k < c;k++) { 78 | int x,y,r; 79 | cin >> x >> y >> r; 80 | Point p = Point(x,y); 81 | Point p2 = t.nearest_vertex(p)->point(); 82 | if(CGAL::squared_distance(p,p2) < r*r) { 83 | contours.push_back(make_pair(Point(x,y),r*r)); 84 | } 85 | } 86 | 87 | Program lp (CGAL::SMALLER, true, 0, false, 0); 88 | int equation = 0; 89 | 90 | // bind supply 91 | for(int i = 0; i < n;i++) { 92 | for(int j = 0; j < m;j++) lp.set_a(i*m + j,equation,1); 93 | lp.set_b(equation,warehouses[i].supply); 94 | equation++; 95 | } 96 | 97 | // bind quantity and alcohol 98 | for(int j = 0; j < m;j++) { 99 | 100 | for(int i = 0; i < n;i++) lp.set_a(i*m + j, equation, 1); 101 | lp.set_b(equation, stadiums[j].demand); 102 | equation++; 103 | 104 | for(int i = 0; i < n;i++) lp.set_a(i*m + j, equation, -1); 105 | lp.set_b(equation, -stadiums[j].demand); 106 | equation++; 107 | 108 | for(int i = 0; i < n;i++) lp.set_a(i*m + j, equation, warehouses[i].alcohol); 109 | lp.set_b(equation, stadiums[j].upper); 110 | equation++; 111 | } 112 | 113 | for(int i = 0; i < n;i++) { 114 | for(int j = 0; j < m;j++) { 115 | int rev = 100*revenues[i][j]; 116 | for(auto c: contours) { 117 | auto dist1 = CGAL::squared_distance(warehouses[i].p,c.first); 118 | auto dist2 = CGAL::squared_distance(stadiums[j].p, c.first); 119 | if(dist1 < c.second && dist2 > c.second) rev--; 120 | if(dist1 > c.second && dist2 < c.second) rev--; 121 | } 122 | lp.set_c(i*m+j, -rev); 123 | } 124 | } 125 | 126 | Solution s = CGAL::solve_linear_program(lp, ET()); 127 | 128 | if(s.is_infeasible()) { 129 | cout << "RIOT!" << "\n"; 130 | return; 131 | } 132 | 133 | cout << floor_to_long(-s.objective_value() / 100) << "\n"; 134 | } 135 | 136 | signed main() { 137 | ios_base::sync_with_stdio(false); 138 | cin.tie(0); 139 | 140 | int t; 141 | cin >> t; 142 | 143 | while(t--) 144 | solve(); 145 | } 146 | -------------------------------------------------------------------------------- /week12/Car Sharing.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define int long 10 | 11 | using namespace std; 12 | 13 | typedef boost::adjacency_list_traits traits; 14 | typedef boost::adjacency_list>>>> graph; 19 | 20 | typedef boost::graph_traits::edge_descriptor edge_desc; 21 | typedef boost::graph_traits::out_edge_iterator out_edge_it; 22 | 23 | class edge_adder 24 | { 25 | graph &G; 26 | 27 | public: 28 | explicit edge_adder(graph &G) : G(G) {} 29 | void add_edge(int from, int to, long capacity, long cost) 30 | { 31 | auto c_map = boost::get(boost::edge_capacity, G); 32 | auto r_map = boost::get(boost::edge_reverse, G); 33 | auto w_map = boost::get(boost::edge_weight, G); // new! 34 | const edge_desc e = boost::add_edge(from, to, G).first; 35 | const edge_desc rev_e = boost::add_edge(to, from, G).first; 36 | c_map[e] = capacity; 37 | c_map[rev_e] = 0; // reverse edge has no capacity! 38 | r_map[e] = rev_e; 39 | r_map[rev_e] = e; 40 | w_map[e] = cost; // new assign cost 41 | w_map[rev_e] = -cost; // new negative cost 42 | } 43 | }; 44 | 45 | struct request { 46 | int from; 47 | int to; 48 | int departure; 49 | int arrival; 50 | int profit; 51 | }; 52 | 53 | vector> compressed; 54 | vector prefix; 55 | 56 | void insert(int station, int time) { 57 | if(compressed[station].find(time) == compressed[station].end()) { 58 | compressed[station][time] = compressed[station].size(); 59 | } 60 | } 61 | 62 | int getIndex(int station, int time) { 63 | return prefix[station] + compressed[station][time]; 64 | } 65 | 66 | void solve() 67 | { 68 | int N,S; 69 | cin >> N >> S; 70 | 71 | const int max_profit = 100; 72 | const int max_time = INT_MAX / 8; 73 | 74 | vector cars = vector(S); 75 | for(int i = 0; i < S;i++) { 76 | cin >> cars[i]; 77 | } 78 | 79 | int nb_cars = accumulate(cars.begin(),cars.end(),0); 80 | 81 | vector requests = vector(N); 82 | for(int i = 0; i < N;i++){ 83 | cin >> requests[i].from; 84 | cin >> requests[i].to; 85 | cin >> requests[i].departure; 86 | cin >> requests[i].arrival; 87 | cin >> requests[i].profit; 88 | requests[i].from--; 89 | requests[i].to--; 90 | } 91 | 92 | compressed = vector>(S); 93 | 94 | for(int i = 0; i < N;i++) { 95 | auto req = requests[i]; 96 | insert(req.from,req.departure); 97 | insert(req.to,req.arrival); 98 | } 99 | 100 | prefix = vector(S); 101 | for(int i = 1; i < S;i++) { 102 | prefix[i] = prefix[i-1] + compressed[i-1].size(); 103 | } 104 | 105 | graph G(prefix[S-1] + compressed[S-1].size()); 106 | edge_adder adder(G); 107 | 108 | auto v_source = boost::add_vertex(G); 109 | auto v_sink = boost::add_vertex(G); 110 | 111 | // Setup graph for stations 112 | for(int i = 0; i < S; i++) { 113 | if(compressed[i].size() == 0) continue; 114 | auto it = compressed[i].begin(); 115 | int prev_time = it->first; 116 | adder.add_edge(v_source,getIndex(i,prev_time),cars[i], (prev_time) * max_profit); 117 | 118 | it++; 119 | for(; it != compressed[i].end(); ++it) { 120 | int curr_time = it->first; 121 | adder.add_edge(getIndex(i,prev_time), getIndex(i, curr_time), INT_MAX, (curr_time - prev_time) * max_profit); 122 | prev_time = curr_time; 123 | } 124 | 125 | adder.add_edge(getIndex(i,prev_time),v_sink, INT_MAX, (max_time - prev_time) * max_profit); 126 | } 127 | 128 | // Setup requests right now 129 | for(const auto &req: requests) { 130 | adder.add_edge(getIndex(req.from,req.departure),getIndex(req.to,req.arrival),1,(req.arrival - req.departure) * max_profit - req.profit); 131 | } 132 | 133 | int flow = boost::push_relabel_max_flow(G,v_source,v_sink); 134 | boost::successive_shortest_path_nonnegative_weights(G, v_source, v_sink); 135 | int cost = boost::find_flow_cost(G); 136 | 137 | cout << flow * max_time * max_profit - cost << "\n"; 138 | } 139 | 140 | signed main() { 141 | ios_base::sync_with_stdio(false); 142 | cin.tie(0); 143 | 144 | int t; 145 | cin >> t; 146 | 147 | while(t--) 148 | solve(); 149 | 150 | return 0; 151 | } 152 | -------------------------------------------------------------------------------- /week12/Lord Voldemort.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define int long 4 | 5 | using namespace std; 6 | 7 | void solve() { 8 | 9 | int n,m,k; 10 | cin >> n >> m >> k; 11 | 12 | vector> dp(m+1,vector(n+1,0)); 13 | vector h(n+1,0); 14 | 15 | for(int i = 1; i <= n;i++) { 16 | cin >> h[i]; 17 | } 18 | 19 | partial_sum(h.begin(),h.end(),h.begin()); 20 | 21 | for(int i = 1; i <= n;i++) { 22 | 23 | // Part 1 : Find a good index 24 | int target = h[i] - k; 25 | auto it = std::lower_bound(h.begin(), h.end(), target); 26 | int j = it - h.begin(); 27 | bool possible = *it == target ? true : false; 28 | 29 | // Part 2 : Update dp table 30 | int toAdd = i-j; 31 | 32 | // First person 33 | if(possible) { 34 | dp[1][i] = toAdd; 35 | } 36 | dp[1][i] = max(dp[1][i],dp[1][i-1]); 37 | 38 | for(int p = 2; p <= m;p++) { 39 | 40 | // Initialize with previous state 41 | dp[p][i] = dp[p][i-1]; 42 | 43 | // Check if we can update the data 44 | if(possible && dp[p-1][j] != 0){ 45 | dp[p][i] = max(dp[p][i],dp[p-1][j] + toAdd); 46 | } 47 | } 48 | } 49 | 50 | if(dp.back().back() == 0) 51 | cout << "fail" << "\n"; 52 | else 53 | cout << dp.back().back() << "\n"; 54 | 55 | return; 56 | } 57 | 58 | 59 | signed main() { 60 | 61 | ios_base::sync_with_stdio(false); 62 | cin.tie(0); 63 | 64 | int t; cin >> t; 65 | 66 | while(t--) 67 | solve(); 68 | 69 | return 0; 70 | } 71 | -------------------------------------------------------------------------------- /week12/Nemean Lion.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define int long 9 | 10 | using namespace std; 11 | 12 | typedef CGAL::Exact_predicates_exact_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 Triangulation; 17 | 18 | typedef CGAL::Point_2 Point; 19 | typedef CGAL::Circle_2 Circle; 20 | 21 | K::FT get_face_radius(Triangulation &t, Triangulation::Face_handle f) { 22 | if(t.is_infinite(f)) return K::FT(LONG_MAX); 23 | return Circle(f->vertex(0)->point(),f->vertex(1)->point(),f->vertex(2)->point()).squared_radius(); 24 | } 25 | 26 | void solve() { 27 | int n,s,h; 28 | cin >> n >> s >> h; 29 | 30 | vector> points(n); 31 | for(int i = 0; i < n;i++) { 32 | int x,y; 33 | cin >> x >> y; 34 | points[i] = make_pair(Point(x,y),i); 35 | } 36 | 37 | Triangulation t; 38 | t.insert(points.begin(),points.end()); 39 | 40 | int a_2 = 0; 41 | int a_3 = 0; 42 | int a_s = 0; 43 | int a_max = 0; 44 | 45 | vector> events; 46 | 47 | auto min_squared_radius = K::FT(LONG_MAX); 48 | for(auto e = t.finite_edges_begin(); e != t.finite_edges_end(); ++e) { 49 | auto v_left = e->first->vertex((e->second + 1) % 3); 50 | auto v_right = e->first->vertex((e->second + 2) % 3); 51 | 52 | Point midpoint = CGAL::midpoint(v_left->point(), v_right->point()); 53 | int v_nearest = t.nearest_vertex(midpoint)->info(); 54 | 55 | auto f1 = e->first; 56 | auto f2 = t.mirror_edge(*e).first; 57 | auto f1_radius = get_face_radius(t,f1); 58 | auto f2_radius = get_face_radius(t,f2); 59 | 60 | K::FT min_radius; 61 | K::FT max_radius = max(f1_radius,f2_radius); 62 | if(v_nearest != v_left->info() && v_nearest != v_right->info()) { 63 | min_radius = min(f1_radius,f2_radius); 64 | } else { 65 | min_radius = t.segment(*e).squared_length() / 4; 66 | } 67 | 68 | if(K::FT(s) >= min_radius && K::FT(s) <= max_radius) { 69 | a_s++; 70 | } 71 | 72 | events.push_back(make_pair(min_radius,0)); 73 | events.push_back(make_pair(max_radius,1)); 74 | 75 | auto distance = t.segment(e).squared_length(); 76 | if(distance < min_squared_radius) { 77 | a_2 = 1; 78 | min_squared_radius = distance; 79 | } else if(distance == min_squared_radius) { 80 | a_2++; 81 | } 82 | } 83 | 84 | auto min_squared_3 = K::FT(LONG_MAX); 85 | for(auto f = t.finite_faces_begin(); f != t.finite_faces_end(); ++f) { 86 | auto radius = get_face_radius(t,f); 87 | if(radius < min_squared_3) { 88 | min_squared_3 = radius; 89 | a_3 = 1; 90 | } else if(radius == min_squared_3) { 91 | a_3++; 92 | } 93 | } 94 | 95 | sort(events.begin(),events.end()); 96 | int curr = 0; 97 | 98 | for(auto e: events) { 99 | if(e.second == 0) curr++; 100 | else curr--; 101 | a_max = max(a_max,curr); 102 | } 103 | 104 | cout << a_2 << " " << a_3 << " " << a_s << " " << a_max << "\n"; 105 | } 106 | 107 | signed main() { 108 | ios_base::sync_with_stdio(false); 109 | cin.tie(0); 110 | 111 | int t; 112 | cin >> t; 113 | 114 | while(t--) 115 | solve(); 116 | } 117 | -------------------------------------------------------------------------------- /week12/Nemean Lion_4.cpp: -------------------------------------------------------------------------------- 1 | ///4 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define int long 10 | 11 | using namespace std; 12 | 13 | typedef CGAL::Exact_predicates_exact_constructions_kernel K; 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 Triangulation; 18 | 19 | typedef CGAL::Point_2 Point; 20 | typedef CGAL::Circle_2 Circle; 21 | 22 | K::FT get_face_radius(Triangulation &t, Triangulation::Face_handle f) { 23 | if(t.is_infinite(f)) return K::FT(LONG_MAX); 24 | return Circle(f->vertex(0)->point(),f->vertex(1)->point(),f->vertex(2)->point()).squared_radius(); 25 | } 26 | 27 | void solve() { 28 | int n,s,h; 29 | cin >> n >> s >> h; 30 | 31 | vector> points(n); 32 | for(int i = 0; i < n;i++) { 33 | int x,y; 34 | cin >> x >> y; 35 | points[i] = make_pair(Point(x,y),i); 36 | } 37 | 38 | Triangulation t; 39 | t.insert(points.begin(),points.end()); 40 | 41 | int a_2 = 0; 42 | int a_3 = 0; 43 | int a_s = 0; 44 | int a_max = 0; 45 | 46 | vector> events; 47 | 48 | auto min_squared_radius = K::FT(LONG_MAX); 49 | for(auto e = t.finite_edges_begin(); e != t.finite_edges_end(); ++e) { 50 | auto v_left = e->first->vertex((e->second + 1) % 3); 51 | auto v_right = e->first->vertex((e->second + 2) % 3); 52 | 53 | Point midpoint = CGAL::midpoint(v_left->point(), v_right->point()); 54 | int v_nearest = t.nearest_vertex(midpoint)->info(); 55 | 56 | auto f1 = e->first; 57 | auto f2 = t.mirror_edge(*e).first; 58 | auto f1_radius = get_face_radius(t,f1); 59 | auto f2_radius = get_face_radius(t,f2); 60 | 61 | K::FT min_radius; 62 | K::FT max_radius = max(f1_radius,f2_radius); 63 | if(v_nearest != v_left->info() && v_nearest != v_right->info()) { 64 | min_radius = min(f1_radius,f2_radius); 65 | } else { 66 | min_radius = t.segment(*e).squared_length() / 4; 67 | } 68 | 69 | if(K::FT(s) >= min_radius && K::FT(s) <= max_radius) { 70 | a_s++; 71 | } 72 | 73 | events.push_back(make_pair(min_radius,true)); 74 | events.push_back(make_pair(max_radius,false)); 75 | 76 | auto distance = t.segment(e).squared_length(); 77 | if(distance < min_squared_radius) { 78 | a_2 = 1; 79 | min_squared_radius = distance; 80 | } else if(distance == min_squared_radius) { 81 | a_2++; 82 | } 83 | } 84 | 85 | auto min_squared_3 = K::FT(LONG_MAX); 86 | for(auto f = t.finite_faces_begin(); f != t.finite_faces_end(); ++f) { 87 | auto radius = get_face_radius(t,f); 88 | if(radius < min_squared_3) { 89 | min_squared_3 = radius; 90 | a_3 = 1; 91 | } else if(radius == min_squared_3) { 92 | a_3++; 93 | } 94 | } 95 | 96 | sort(events.begin(),events.end()); 97 | int curr = 0; 98 | 99 | for(auto e: events) { 100 | if(e.second) curr++; 101 | else curr--; 102 | a_max = max(a_max,curr); 103 | } 104 | 105 | cout << a_2 << " " << a_3 << " " << a_s << " " << a_max << "\n"; 106 | } 107 | 108 | signed main() { 109 | ios_base::sync_with_stdio(false); 110 | cin.tie(0); 111 | 112 | int t; 113 | cin >> t; 114 | 115 | while(t--) 116 | solve(); 117 | } 118 | -------------------------------------------------------------------------------- /week12/On Her Majesty's Secret Service.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | // BGL includes 3 | #include 4 | #include 5 | #include 6 | 7 | typedef boost::adjacency_list > graph; 9 | 10 | typedef boost::adjacency_list graph_undirected; 12 | typedef boost::graph_traits::vertex_descriptor vertex_desc_undirected; 13 | 14 | using namespace std; 15 | 16 | int n,m,a,s,c,d; 17 | vector> dist_map; 18 | vector agents; 19 | vector shelters; 20 | 21 | bool valid(int distance) { 22 | 23 | graph_undirected G(a + s*c); 24 | 25 | int asize = agents.size(); 26 | int ssize = shelters.size(); 27 | 28 | for(int i = 0; i < asize; i++) { 29 | for(int j = 0; j < ssize; j++) { 30 | 31 | int aindex = agents[i]; 32 | int sindex = shelters[j]; 33 | 34 | if(dist_map[aindex][sindex] == INT_MAX) 35 | continue; 36 | 37 | if(dist_map[aindex][sindex] + d <= distance) 38 | boost::add_edge(i,asize + j,G); 39 | if(c == 2 && dist_map[aindex][sindex] + 2*d <= distance) 40 | boost::add_edge(i,asize+ssize+j,G); 41 | } 42 | } 43 | 44 | int size = boost::num_vertices(G); 45 | std::vector mate_map(size); 46 | 47 | boost::edmonds_maximum_cardinality_matching(G, 48 | boost::make_iterator_property_map(mate_map.begin(), boost::get(boost::vertex_index, G))); 49 | 50 | int matching_size = boost::matching_size(G, 51 | boost::make_iterator_property_map(mate_map.begin(), boost::get(boost::vertex_index, G))); 52 | 53 | return matching_size == asize; 54 | } 55 | 56 | void solve() { 57 | 58 | cin >> n >> m >> a >> s >> c >> d; 59 | 60 | graph G(n); 61 | 62 | for(int i = 0; i < m;i++) { 63 | char w; 64 | int x,y,z; 65 | cin >> w >> x >> y >> z; 66 | 67 | if(w == 'S') { 68 | boost::add_edge(x,y,z,G); 69 | } 70 | if(w == 'L') { 71 | boost::add_edge(x,y,z,G); 72 | boost::add_edge(y,x,z,G); 73 | } 74 | } 75 | 76 | agents = vector(a); 77 | shelters = vector(s); 78 | 79 | for(int i = 0; i < a;i++) { 80 | cin >> agents[i]; 81 | } 82 | for(int i = 0; i < s;i++) { 83 | cin >> shelters[i]; 84 | } 85 | 86 | dist_map = vector>(n,vector(n)); 87 | 88 | for(int from = 0; from < n;from++) { 89 | boost::dijkstra_shortest_paths(G, from ,boost::distance_map(boost::make_iterator_property_map( 90 | dist_map[from].begin(), boost::get(boost::vertex_index, G)))); 91 | } 92 | 93 | // Binary search on the solution space 94 | int start = 0; 95 | int end = INT_MAX / 2; 96 | 97 | while(start < end) { 98 | int middle = (start + end) / 2; 99 | if(valid(middle)) { 100 | end = middle; 101 | } 102 | else { 103 | start = middle+1; 104 | } 105 | } 106 | 107 | cout << start << endl; 108 | 109 | return; 110 | } 111 | 112 | signed main() { 113 | 114 | ios_base::sync_with_stdio(false); 115 | cin.tie(0); 116 | 117 | int t; 118 | cin >> t; 119 | 120 | while(t--) 121 | solve(); 122 | 123 | } -------------------------------------------------------------------------------- /week13/Asterix and the Chariot Race.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define int long 4 | 5 | using namespace std; 6 | 7 | struct City { 8 | int repared; 9 | int noneed; 10 | int need; 11 | }; 12 | 13 | vector> graph; 14 | vector costs; 15 | vector dp; 16 | 17 | void compute(int idx) { 18 | // Base case 19 | if(graph[idx].size() == 0) { 20 | dp[idx] = {costs[idx],costs[idx],0}; 21 | return; 22 | } 23 | 24 | // Recursive case 25 | City tmp = {0,0,0}; 26 | for(auto child: graph[idx]) { 27 | compute(child); 28 | } 29 | 30 | // Case 1 31 | tmp.repared = costs[idx]; 32 | for(auto child: graph[idx]) { 33 | tmp.repared += min({dp[child].repared,dp[child].noneed,dp[child].need}); 34 | 35 | } 36 | // Case 2 37 | int min_diff = INT_MAX; 38 | for(auto child: graph[idx]) { 39 | tmp.noneed += min({dp[child].repared,dp[child].noneed}); 40 | min_diff = min(min_diff, dp[child].repared - dp[child].noneed); 41 | } 42 | tmp.noneed += max(0l,min_diff); 43 | tmp.noneed = min(tmp.repared,tmp.noneed); 44 | 45 | // Case 3 46 | for(auto child: graph[idx]) { 47 | tmp.need += min({dp[child].repared,dp[child].noneed}); 48 | } 49 | 50 | dp[idx] = tmp; 51 | } 52 | 53 | void solve() { 54 | int n; 55 | cin >> n; 56 | 57 | graph = vector>(n,vector(0)); 58 | for(int i = 0; i < n-1;i++) { 59 | int from; 60 | int to; 61 | cin >> from >> to; 62 | graph[from].push_back(to); 63 | } 64 | 65 | costs = vector(n); 66 | for(int i = 0; i < n;i++) cin >> costs[i]; 67 | 68 | dp = vector(n); 69 | 70 | compute(0); 71 | cout << min(dp[0].repared, dp[0].noneed) << "\n"; 72 | } 73 | 74 | signed main() { 75 | ios_base::sync_with_stdio(false); 76 | cin.tie(0); 77 | 78 | int t; 79 | cin >> t; 80 | 81 | while(t--) 82 | solve(); 83 | } 84 | -------------------------------------------------------------------------------- /week13/Evolution.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define int long 4 | 5 | using namespace std; 6 | 7 | struct Spec { 8 | string name; 9 | int age; 10 | }; 11 | 12 | struct Query { 13 | int max_age; 14 | int idx; 15 | }; 16 | 17 | struct Path { 18 | int index; 19 | int age; 20 | }; 21 | 22 | vector> graph; 23 | vector> queries; 24 | vector solutions; 25 | vector species; 26 | 27 | vector path; 28 | 29 | void dfs(int idx) { 30 | path.push_back({idx, species[idx].age}); 31 | 32 | for(auto q: queries[idx]) solutions[q.idx] = std::lower_bound(path.begin(), path.end(), Path{0,q.max_age}, [](Path a, Path b) { 33 | return a.age > b.age; 34 | })->index; 35 | 36 | for(auto c: graph[idx]) dfs(c); 37 | 38 | path.pop_back(); 39 | } 40 | 41 | void solve() { 42 | 43 | int n,q; 44 | cin >> n >> q; 45 | 46 | map conv; 47 | 48 | species = vector(n); 49 | for(int i = 0; i < n;i++) { 50 | string name; 51 | int age; 52 | cin >> name >> age; 53 | species[i] = Spec{name,age}; 54 | conv[species[i].name] = i; 55 | } 56 | 57 | graph = vector>(n,vector(0)); 58 | vector isChild = vector(n,false); 59 | 60 | for(int i = 0; i < n-1;i++) { 61 | string a,b; 62 | cin >> a >> b; 63 | int from = conv[b]; 64 | int to = conv[a]; 65 | graph[from].push_back(to); 66 | isChild[to] = true; 67 | } 68 | 69 | int root = 0; 70 | for(int i = 0; i < n;i++) { 71 | if(!isChild[i]) { 72 | root = i; 73 | break; 74 | } 75 | } 76 | 77 | queries = vector>(n, vector(0)); 78 | solutions = vector(q); 79 | 80 | for(int i = 0; i < q;i++) { 81 | string name; int age; 82 | cin >> name >> age; 83 | int idx = conv[name]; 84 | queries[idx].push_back(Query{age,i}); 85 | } 86 | 87 | path = vector(0); 88 | 89 | dfs(root); 90 | 91 | for(auto ans: solutions) { 92 | cout << species[ans].name << " "; 93 | } 94 | 95 | cout << endl; 96 | } 97 | 98 | signed main() { 99 | ios_base::sync_with_stdio(false); 100 | cin.tie(nullptr); 101 | 102 | int t; 103 | cin >> t; 104 | 105 | while(t--) 106 | solve(); 107 | } 108 | -------------------------------------------------------------------------------- /week13/Idéfix.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #define int long 11 | 12 | typedef CGAL::Exact_predicates_inexact_constructions_kernel K; 13 | 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 Triangulation; 18 | typedef CGAL::Point_2 Point; 19 | 20 | typedef Triangulation::Edge Edge; 21 | 22 | using namespace std; 23 | 24 | struct Bone { 25 | Point p; 26 | int idx; 27 | K::FT dist; 28 | }; 29 | 30 | void solve() { 31 | 32 | int n,m,s,k; 33 | cin >> n >> m >> s >> k; 34 | 35 | vector> positions = vector>(n); 36 | vector bones = vector(m); 37 | 38 | for(int i = 0; i < n;i++) { 39 | int x,y; 40 | cin >> x >> y; 41 | positions[i] = make_pair(Point(x,y),i); 42 | } 43 | 44 | for(int j = 0; j < m;j++) { 45 | int x,y; 46 | cin >> x >> y; 47 | bones[j] = {Point(x,y),0,0}; 48 | } 49 | 50 | Triangulation t; 51 | t.insert(positions.begin(),positions.end()); 52 | 53 | boost::disjoint_sets_with_storage<> uf(n); 54 | 55 | for(auto e = t.finite_edges_begin(); e != t.finite_edges_end(); ++e) { 56 | auto s1 = e->first->vertex((e->second + 1) % 3); 57 | auto s2 = e->first->vertex((e->second + 2) % 3); 58 | if(CGAL::squared_distance(s1->point(),s2->point()) <= s) { 59 | uf.link(s1->info(),s2->info()); 60 | } 61 | } 62 | 63 | vector values = vector(n,0); 64 | for(auto bone : bones) { 65 | Point p = t.nearest_vertex(bone.p)->point(); 66 | int idx = t.nearest_vertex(bone.p)->info(); 67 | if(CGAL::squared_distance(p,bone.p) <= s / 4) { 68 | values[uf.find_set(idx)]++; 69 | } 70 | } 71 | 72 | vector edges = vector(0); 73 | 74 | for(auto e = t.finite_edges_begin(); e != t.finite_edges_end(); ++e) { 75 | edges.push_back(*e); 76 | } 77 | 78 | for(int j = 0; j < m;j++) { 79 | auto tmp = t.nearest_vertex(bones[j].p); 80 | bones[j].idx = tmp->info(); 81 | bones[j].dist = CGAL::squared_distance(tmp->point(),bones[j].p); 82 | } 83 | 84 | sort(edges.begin(),edges.end(), [&](auto e1, auto e2) -> bool { 85 | return t.segment(e1).squared_length() < t.segment(e2).squared_length(); 86 | }); 87 | 88 | sort(bones.begin(),bones.end(), [&](auto b1, auto b2) -> bool { 89 | return b1.dist < b2.dist; 90 | }); 91 | 92 | int start = 0; 93 | int end = 1e16; 94 | 95 | int dist = 0; 96 | 97 | while(start != end) { 98 | 99 | boost::disjoint_sets_with_storage<> uf(n); 100 | 101 | dist = (start + end) / 2; 102 | 103 | for(auto e: edges) { 104 | auto s1 = e.first->vertex((e.second + 1) % 3); 105 | auto s2 = e.first->vertex((e.second + 2) % 3); 106 | if(CGAL::squared_distance(s1->point(),s2->point()) <= dist) { 107 | uf.link(s1->info(),s2->info()); 108 | } else { 109 | break; 110 | } 111 | } 112 | 113 | vector values = vector(n,0); 114 | for(auto bone : bones) { 115 | if(bone.dist <= dist / 4) { 116 | values[uf.find_set(bone.idx)]++; 117 | } else { 118 | break; 119 | } 120 | } 121 | 122 | if(*max_element(values.begin(),values.end()) < k) { 123 | start = dist+1; 124 | } else { 125 | end = dist; 126 | } 127 | 128 | } 129 | 130 | cout << std::fixed << *max_element(values.begin(),values.end()) << " " << max(dist,start) << "\n"; 131 | } 132 | 133 | signed main() { 134 | 135 | ios_base::sync_with_stdio(false); 136 | cin.tie(0); 137 | 138 | int t; 139 | cin >> t; 140 | 141 | while(t--) 142 | solve(); 143 | } 144 | -------------------------------------------------------------------------------- /week13/Marathon.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | typedef boost::adjacency_list> graph; 10 | 11 | // Graph Type with nested interior edge properties for flow algorithms 12 | typedef boost::adjacency_list_traits traits; 13 | typedef boost::adjacency_list>>> graph_flow; 17 | 18 | // Custom edge adder class, highly recommended 19 | class edge_adder { 20 | graph_flow &G; 21 | 22 | public: 23 | explicit edge_adder(graph_flow &G) : G(G) {} 24 | 25 | void add_edge(int from, int to, long capacity) { 26 | auto c_map = boost::get(boost::edge_capacity, G); 27 | auto r_map = boost::get(boost::edge_reverse, G); 28 | const auto e = boost::add_edge(from, to, G).first; 29 | const auto rev_e = boost::add_edge(to, from, G).first; 30 | c_map[e] = capacity; 31 | c_map[rev_e] = 0; // reverse edge has no capacity! 32 | r_map[e] = rev_e; 33 | r_map[rev_e] = e; 34 | } 35 | }; 36 | 37 | struct Edge { 38 | int from; 39 | int to; 40 | int width; 41 | int length; 42 | }; 43 | 44 | vector dijkstra_dist(const graph &G, int s) { 45 | int n = boost::num_vertices(G); 46 | std::vector dist_map(n); 47 | 48 | boost::dijkstra_shortest_paths(G, s, 49 | boost::distance_map(boost::make_iterator_property_map( 50 | dist_map.begin(), boost::get(boost::vertex_index, G)))); 51 | 52 | return dist_map; 53 | } 54 | 55 | 56 | void solve() { 57 | 58 | int n,m,s,f; 59 | cin >> n >> m >> s >> f; 60 | 61 | vector edges = vector(m); 62 | for(int i = 0; i < m;i++) { 63 | cin >> edges[i].from; 64 | cin >> edges[i].to; 65 | cin >> edges[i].width; 66 | cin >> edges[i].length; 67 | } 68 | 69 | graph G(n); 70 | for(int i = 0; i < m;i++) { 71 | boost::add_edge(edges[i].from,edges[i].to, edges[i].length, G); 72 | } 73 | 74 | vector dist = dijkstra_dist(G,s); 75 | 76 | graph_flow G_flow(n); 77 | edge_adder adder(G_flow); 78 | 79 | for(auto edge: edges) { 80 | 81 | int a = edge.from; 82 | int b = edge.to; 83 | int length = edge.length; 84 | int width = edge.width; 85 | 86 | if(dist[a] + length == dist[b]) adder.add_edge(a,b,width); 87 | if(dist[b] + length == dist[a]) adder.add_edge(b,a,width); 88 | } 89 | 90 | cout << boost::push_relabel_max_flow(G_flow, s, f) << endl; 91 | } 92 | 93 | int main() { 94 | 95 | ios_base::sync_with_stdio(false); 96 | cin.tie(0); 97 | 98 | int t; cin >> t; 99 | while(t--) 100 | solve(); 101 | 102 | return 0; 103 | } 104 | -------------------------------------------------------------------------------- /week2/Beach Bars.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | 9 | void solve() { 10 | 11 | int n; 12 | cin >>n; 13 | 14 | vector a(n); 15 | for(int i = 0; i < n;i++) 16 | cin >> a[i]; 17 | 18 | sort(a.begin(),a.end()); 19 | 20 | int score = 0; 21 | int start = -1; 22 | int end = 0; 23 | 24 | int max_score = INT_MIN; 25 | int left = 0; 26 | int right = 0; 27 | 28 | vector solutions(0); 29 | int max_distance = 101; 30 | 31 | while(start != n - 1) { 32 | 33 | start++; 34 | score++; 35 | 36 | while(end < start && a[start] - a[end] > 200) { 37 | end++; 38 | score--; 39 | } 40 | 41 | bool c1 = score > max_score; 42 | bool c2 = score == max_score && (a[start] - a[end] + 1) / 2 < max_distance; 43 | 44 | if(c1 || c2) { 45 | max_score = score; 46 | left = end; 47 | right = start; 48 | 49 | max_distance = (a[start] - a[end] + 1) / 2; 50 | solutions = vector(0); 51 | 52 | if((a[start] - a[end]) % 2 == 1) 53 | solutions.push_back(a[end] + (a[start]-a[end]) / 2); 54 | 55 | solutions.push_back(a[end] + (a[start]-a[end]+1) / 2); 56 | } 57 | 58 | else if(score == max_score && (a[start] - a[end] + 1) / 2 == max_distance) { 59 | if((a[start] - a[end]) % 2 == 1) { 60 | solutions.push_back(a[end] + (a[start]-a[end]) / 2); 61 | } 62 | 63 | solutions.push_back(a[end] + (a[start]-a[end]+1) / 2); 64 | } 65 | } 66 | 67 | cout << max_score << " " << (a[right] - a[left] + 1) / 2 << "\n"; 68 | 69 | for(auto e : solutions) { 70 | cout << e << " "; 71 | } 72 | cout << "\n"; 73 | 74 | return; 75 | } 76 | 77 | int main() { 78 | 79 | ios_base::sync_with_stdio(false); 80 | cin.tie(NULL); 81 | 82 | int t; 83 | cin >> t; 84 | 85 | while(t--) 86 | solve(); 87 | 88 | } 89 | -------------------------------------------------------------------------------- /week2/Burning Coins.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | vector a; 7 | vector> dp; 8 | 9 | int compute(int start, int end, int player) { 10 | 11 | if(dp[start][end] != -1) 12 | return dp[start][end]; 13 | 14 | if(start >= end) { 15 | return player == 0 ? a[start] : 0; 16 | } 17 | 18 | if(player == 1) { 19 | dp[start][end] = min(compute(start+1,end,0),compute(start,end-1,0)); 20 | } 21 | 22 | else { 23 | dp[start][end] = max(a[start]+compute(start+1,end,1),a[end]+compute(start,end-1,1)); 24 | } 25 | 26 | return dp[start][end]; 27 | } 28 | 29 | void solve() { 30 | 31 | int n; 32 | cin >> n; 33 | 34 | a = vector(n); 35 | dp = vector>(n,vector(n,-1)); 36 | for(int i = 0; i < n;i++) { 37 | cin >> a[i]; 38 | } 39 | 40 | if(n == 1) { 41 | cout << a.back() << "\n"; 42 | return; 43 | } 44 | 45 | int output = max(a[0]+compute(1,n-1,1),a.back()+compute(0,n-2,1)); 46 | 47 | cout << output <<"\n"; 48 | } 49 | 50 | int main() { 51 | 52 | int t; 53 | cin >> t; 54 | 55 | while(t--) 56 | solve(); 57 | 58 | } 59 | -------------------------------------------------------------------------------- /week2/Search Snippets.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | struct entry { 9 | int word; 10 | int position; 11 | }; 12 | 13 | void solve() { 14 | 15 | int n; 16 | cin >> n; 17 | 18 | vector m(n); 19 | for(int i = 0; i < n;i++) 20 | cin >> m[i]; 21 | 22 | vector words(0); 23 | 24 | for(int i = 0; i < n;i++) { 25 | for(int j = 0; j < m[i];j++) { 26 | int tmp; 27 | cin >> tmp; 28 | words.push_back({i,tmp}); 29 | } 30 | } 31 | 32 | sort(words.begin(),words.end(), [](entry a,entry b) -> bool { 33 | return a.position < b.position; 34 | }); 35 | 36 | int start = -1; 37 | int end = 0; 38 | 39 | int best = INT_MAX; 40 | 41 | vector pos(n,-1); 42 | int count = 0; 43 | 44 | while(start != words.size() - 1 ) { 45 | start++; 46 | 47 | int word = words[start].word; 48 | int position = words[start].position; 49 | 50 | if(pos[word] == -1) 51 | count++; 52 | 53 | pos[word] = position; 54 | 55 | while(pos[words[end].word] != words[end].position) { 56 | end++; 57 | } 58 | 59 | if(count == n) { 60 | best = min(best,words[start].position - words[end].position + 1); 61 | } 62 | 63 | } 64 | 65 | cout << best << "\n"; 66 | 67 | return; 68 | } 69 | 70 | int main() { 71 | 72 | ios_base::sync_with_stdio(false); 73 | cin.tie(NULL); 74 | 75 | int t; 76 | cin >> t; 77 | 78 | while(t--) 79 | solve(); 80 | 81 | } 82 | -------------------------------------------------------------------------------- /week2/The Great Game.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | vector> graph; 10 | vector> dp; 11 | 12 | int distance(int idx,int player) { 13 | 14 | if(dp[idx][player] != -1) { 15 | return dp[idx][player]; 16 | } 17 | 18 | if(idx == graph.size() - 1) 19 | return 0; 20 | 21 | vector v(0); 22 | for(auto next : graph[idx]) { 23 | v.push_back(distance(next,1-player)); 24 | } 25 | 26 | int dist = player % 2 == 0 ? *min_element(v.begin(),v.end()) : *max_element(v.begin(),v.end()); 27 | dist++; 28 | 29 | dp[idx][player] = dist; 30 | 31 | return dist; 32 | } 33 | 34 | void solve() { 35 | 36 | int n,m; 37 | cin >> n >> m; 38 | 39 | int r,bl; 40 | cin >> r >> bl; 41 | r--; 42 | bl--; 43 | 44 | graph = vector>(n,vector(0)); 45 | for(int i = 0; i < m;i++) { 46 | int a,b; 47 | cin >> a >> b; 48 | graph[a-1].push_back(b-1); 49 | } 50 | 51 | dp = vector>(n,vector(2,-1)); 52 | 53 | int dist_red = distance(r,0); 54 | int dist_black = distance(bl,0); 55 | 56 | if(dist_red < dist_black) { 57 | cout << 0 << "\n"; 58 | } else if(dist_black < dist_red){ 59 | cout << 1 << "\n"; 60 | } else { 61 | cout << (dist_red % 2 == 0) << "\n"; 62 | } 63 | 64 | return; 65 | } 66 | 67 | int main() { 68 | 69 | ios_base::sync_with_stdio(false); 70 | cin.tie(NULL); 71 | 72 | int t; 73 | cin >> t; 74 | 75 | while(t--) { 76 | solve(); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /week3/Ant Challenge.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #define int long 8 | 9 | using namespace std; 10 | 11 | typedef boost::adjacency_list > graph; 13 | typedef boost::property_map::type weight_map; 14 | typedef boost::graph_traits::edge_descriptor edge_desc; 15 | typedef boost::graph_traits::vertex_descriptor vertex_desc; 16 | 17 | int dijkstra_dist(const graph &G, int s, int t) { 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 | return dist_map[t]; 26 | } 27 | 28 | void solve() { 29 | int n,e,s,a,b; 30 | cin >> n >> e >> s >> a >> b; 31 | 32 | vector networks(s,graph(n)); 33 | for(int i = 0; i < e;i++) { 34 | int from,to; 35 | cin >> from >> to; 36 | for(int j = 0; j < s;j++) { 37 | int w; 38 | cin >> w; 39 | boost::add_edge(from,to,w,networks[j]); 40 | } 41 | } 42 | 43 | int tmp; 44 | for(int i = 0; i < s; i++) cin >> tmp; 45 | 46 | graph final(n); 47 | 48 | for(auto net : networks) { 49 | std::vector mst; 50 | boost::kruskal_minimum_spanning_tree(net, std::back_inserter(mst)); 51 | 52 | auto weights = boost::get(boost::edge_weight,net); 53 | 54 | for (std::vector::iterator it = mst.begin(); it != mst.end(); ++it) { 55 | boost::add_edge(boost::source(*it, net),boost::target(*it, net),weights[*it],final); 56 | } 57 | } 58 | 59 | cout << dijkstra_dist(final,a,b) << endl; 60 | } 61 | 62 | signed main() { 63 | ios_base::sync_with_stdio(false); 64 | cin.tie(0); 65 | 66 | int t; 67 | cin >> t; 68 | 69 | while(t--) 70 | solve(); 71 | 72 | return 0; 73 | } 74 | -------------------------------------------------------------------------------- /week3/Buddy Selection.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | typedef boost::adjacency_list graph; 10 | typedef boost::graph_traits::vertex_descriptor vertex_desc; 11 | 12 | using namespace std; 13 | 14 | void solve() { 15 | 16 | int n,c,f; 17 | cin >> n >> c >> f; 18 | 19 | vector> car = vector>(n,set()); 20 | 21 | for(int i = 0; i < n;i++) { 22 | for(int j = 0; j < c;j++) { 23 | string s; 24 | cin >> s; 25 | car[i].insert(s); 26 | } 27 | } 28 | 29 | graph G(n); 30 | 31 | for(int i = 0; i < n;i++) { 32 | for(int j = 0; j < i;j++) { 33 | vector intersection; 34 | set_intersection(car[i].begin(),car[i].end(),car[j].begin(),car[j].end(),back_inserter(intersection)); 35 | if(intersection.size() > f) { 36 | boost::add_edge(i,j,G); 37 | } 38 | } 39 | } 40 | 41 | vector mate_map(n); 42 | 43 | boost::edmonds_maximum_cardinality_matching(G,boost::make_iterator_property_map(mate_map.begin(),boost::get(boost::vertex_index,G))); 44 | 45 | int matching_size = boost::matching_size(G,boost::make_iterator_property_map(mate_map.begin(),boost::get(boost::vertex_index,G))); 46 | 47 | if(2*matching_size == n) { 48 | cout << "not optimal\n"; 49 | } else { 50 | cout << "optimal\n"; 51 | } 52 | 53 | return; 54 | } 55 | 56 | int main() { 57 | 58 | int t; 59 | cin >> t; 60 | 61 | while(t--) 62 | solve(); 63 | 64 | } 65 | -------------------------------------------------------------------------------- /week3/First steps with BGL.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | typedef boost::adjacency_list> graph; 11 | typedef boost::graph_traits::edge_descriptor edge_descriptor; 12 | typedef boost::property_map::type edge_weights; 13 | 14 | int mst_size(graph &G) { 15 | 16 | vector mst(0); 17 | 18 | boost::kruskal_minimum_spanning_tree(G,back_inserter(mst)); 19 | 20 | edge_weights e = get(boost::edge_weight, G); 21 | 22 | unsigned int sum = 0; 23 | for(auto it = mst.begin();it != mst.end(); ++it) { 24 | sum += e[*it]; 25 | } 26 | 27 | return sum; 28 | } 29 | 30 | int dist_max(graph &G) { 31 | 32 | int n = boost::num_vertices(G); 33 | 34 | vector d(n); 35 | 36 | boost::dijkstra_shortest_paths(G,0,boost::distance_map(boost::make_iterator_property_map(d.begin(),boost::get(boost::vertex_index,G)))); 37 | 38 | return *max_element(d.begin(),d.end()); 39 | } 40 | 41 | void solve() { 42 | int n,m; 43 | cin >> n >> m; 44 | 45 | graph G(n); 46 | 47 | for(int i = 0; i < m;i++) { 48 | int a,b,c; 49 | cin >> a >> b >> c; 50 | add_edge(a,b,c,G); 51 | } 52 | 53 | cout << mst_size(G) << " " << dist_max(G) << "\n"; 54 | return; 55 | } 56 | 57 | int main() { 58 | 59 | int t; 60 | cin >> t; 61 | 62 | while(t--) 63 | solve(); 64 | } 65 | -------------------------------------------------------------------------------- /week3/Important Bridges.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #define int long 7 | 8 | using namespace std; 9 | 10 | namespace boost 11 | { 12 | struct edge_component_t 13 | { 14 | enum 15 | { num = 555 }; 16 | typedef edge_property_tag kind; 17 | } 18 | edge_component; 19 | } 20 | 21 | typedef boost::adjacency_list> graph; 22 | typedef boost::graph_traits::edge_descriptor edge_descriptor; 23 | typedef boost::graph_traits::vertex_descriptor vertex_descriptor; 24 | 25 | void solve() { 26 | int n,m; 27 | cin >> n >> m; 28 | 29 | graph G(n); 30 | 31 | for(int i = 0; i < m;i++) { 32 | int a,b; 33 | cin >> a >> b; 34 | boost::add_edge(a,b,G); 35 | } 36 | 37 | boost::property_map::type component = boost::get(boost::edge_component,G); 38 | int nums_components = biconnected_components(G,component); 39 | 40 | vector> connections(nums_components,vector(0)); 41 | 42 | boost::graph_traits::edge_iterator ei, ei_end; 43 | for (boost::tie(ei, ei_end) = edges(G); ei != ei_end; ++ei) { 44 | connections[component[*ei]].push_back(*ei); 45 | } 46 | 47 | vector> results(0); 48 | 49 | for(int i = 0; i < nums_components;i++) { 50 | if(connections[i].size() == 1) { 51 | int u = boost::source(connections[i][0],G); 52 | int v = boost::target(connections[i][0],G); 53 | results.push_back(make_pair(min(u,v),max(u,v))); 54 | } 55 | } 56 | 57 | sort(results.begin(),results.end(),[](pair const &a, pair const &b) -> bool { 58 | return a.first < b.first || (a.first == b.first && a.second < b.second); 59 | }); 60 | 61 | cout << results.size() << "\n"; 62 | for(auto e : results) { 63 | cout << e.first << " " << e.second << "\n"; 64 | } 65 | } 66 | 67 | signed main() { 68 | ios_base::sync_with_stdio(false); 69 | cin.tie(0); 70 | 71 | int t; 72 | cin >> t; 73 | 74 | while(t--) 75 | solve(); 76 | } 77 | -------------------------------------------------------------------------------- /week4/Antenna.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #define int long 8 | 9 | using namespace std; 10 | 11 | typedef CGAL::Exact_predicates_exact_constructions_kernel_with_sqrt K; 12 | typedef CGAL::Point_2 Point; 13 | typedef CGAL::Min_circle_2_traits_2 Traits; 14 | typedef CGAL::Min_circle_2 Min_circle; 15 | 16 | double ceil_to_double(const K::FT& x) { 17 | double a = ceil(CGAL::to_double(x)); 18 | while(a < x) a += 1; 19 | while(a-1 >= x) a -= 1; 20 | return a; 21 | } 22 | 23 | void solve(int n) { 24 | vector points(n); 25 | 26 | for(int i = 0; i < n;i++) { 27 | int x,y; 28 | cin >> x >> y; 29 | points[i] = Point(x,y); 30 | } 31 | 32 | Min_circle mc(points.begin(), points.end(), true); 33 | Traits::Circle c = mc.circle(); 34 | cout << fixed << setprecision(0); 35 | std::cout << ceil_to_double(sqrt(c.squared_radius())) << "\n"; 36 | } 37 | 38 | signed main() { 39 | ios_base::sync_with_stdio(false); 40 | cin.tie(0); 41 | 42 | int n; 43 | cin >> n; 44 | 45 | while(n != 0) { 46 | solve(n); 47 | cin >> n; 48 | } 49 | 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /week4/First Hit.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | typedef CGAL::Exact_predicates_exact_constructions_kernel K; 10 | typedef CGAL::Ray_2 Ray; 11 | typedef CGAL::Point_2 Point; 12 | typedef CGAL::Segment_2 Segment; 13 | typedef K::FT FT; 14 | 15 | using namespace std; 16 | 17 | double floor_to_double(const K::FT& x) { 18 | double a = std::floor(CGAL::to_double(x)); 19 | while (a > x) a -= 1; 20 | while (a+1 <= x) a += 1; 21 | return a; 22 | } 23 | 24 | Point getPoint(Point &start, Ray &ray, Segment &seg) { 25 | 26 | auto o = CGAL::intersection(ray,seg); 27 | 28 | if(const Point* op = boost::get(&*o)) { 29 | return *op; 30 | } 31 | 32 | else if(const Segment *s = boost::get(&*o)) { 33 | Point p1 = s->source(); 34 | Point p2 = s->target(); 35 | 36 | auto dist1 = CGAL::squared_distance(p1,start); 37 | auto dist2 = CGAL::squared_distance(p2,start); 38 | 39 | return dist1 < dist2 ? p1 : p2; 40 | } 41 | 42 | return Point(0,0); 43 | } 44 | 45 | void solve(int n) { 46 | 47 | long int a,b,x,y; 48 | cin >> a >> b >> x >> y; 49 | Ray ray = Ray(Point(a,b),Point(x,y)); 50 | Point start = Point(a,b); 51 | 52 | vector segments(0); 53 | for(int i = 0; i < n;i++) { 54 | long int a,b,c,d; 55 | cin >> a >> b >> c >> d; 56 | segments.push_back(Segment(Point(a,b),Point(c,d))); 57 | } 58 | 59 | random_shuffle(segments.begin(),segments.end()); 60 | 61 | bool hit = false; 62 | Point answer; 63 | 64 | int i = 0; 65 | for(;i < segments.size();i++) { 66 | if(CGAL::do_intersect(ray,segments [i])) { 67 | hit = true; 68 | answer = getPoint(start,ray,segments[i]); 69 | break; 70 | } 71 | } 72 | 73 | if(!hit) { 74 | cout << "no" << "\n"; 75 | return; 76 | } 77 | 78 | for(; i < segments.size(); i++) { 79 | Segment new_ray(start,answer); 80 | 81 | if(CGAL::do_intersect(new_ray,segments[i])) { 82 | answer = getPoint(start,ray,segments[i]); 83 | } 84 | } 85 | cout << setiosflags(ios::fixed) << setprecision(0); 86 | cout << floor_to_double(answer.x()) << " " << floor_to_double(answer.y()) << "\n"; 87 | } 88 | 89 | signed main() { 90 | 91 | ios_base::sync_with_stdio(false); 92 | cin.tie(NULL); 93 | 94 | int n; 95 | cin >> n; 96 | 97 | while(n != 0) { 98 | solve(n); 99 | cin >> n; 100 | } 101 | 102 | } 103 | -------------------------------------------------------------------------------- /week4/Hiking Map.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | typedef CGAL::Exact_predicates_exact_constructions_kernel K; 6 | typedef CGAL::Point_2 Point; 7 | typedef CGAL::Line_2 Line; 8 | typedef CGAL::Triangle_2 Triangle; 9 | 10 | using namespace std; 11 | 12 | inline Point read_point() { 13 | int x,y; cin >> x >> y; 14 | return Point(x,y); 15 | } 16 | 17 | inline bool check(const vector &points, const Point &point) { 18 | return !CGAL::right_turn(points[0],points[1],point) && !CGAL::right_turn(points[2],points[3],point) && !CGAL::right_turn(points[4],points[5],point); 19 | } 20 | 21 | void solve() { 22 | int n,m; 23 | cin >> m >> n; 24 | 25 | vector points = vector(m); 26 | for(int i = 0; i < m;i++) { 27 | points[i] = read_point(); 28 | } 29 | 30 | vector> triangles = vector>(n,vector(0)); 31 | for(int i = 0; i < n; i++) { 32 | for(int j = 0; j < 6; j++) { 33 | int x,y; 34 | cin >> x >> y; 35 | triangles[i].push_back(Point(x,y)); 36 | } 37 | for(int j = 0; j < 6;j+=2) { 38 | if(CGAL::right_turn(triangles[i][j],triangles[i][j+1],triangles[i][(j+2) % 6])) std::swap(triangles[i][j],triangles[i][j+1]); 39 | } 40 | } 41 | 42 | vector> contains(n,vector(m-1,false)); 43 | 44 | for(int i = 0; i < n;i++) { 45 | vector inside(m,false); 46 | for(int j = 0; j < m;j++) { 47 | if(check(triangles[i],points[j])) 48 | inside[j] = true; 49 | } 50 | for(int j = 0; j < m-1;j++) { 51 | if(inside[j] && inside[j+1]) contains[i][j] = true; 52 | } 53 | } 54 | 55 | int best = INT_MAX; 56 | int start = -1; 57 | int end = 0; 58 | 59 | int counter = 0; 60 | vector mask(m-1,0); 61 | 62 | while(start != n-1) { 63 | start++; 64 | for(int j = 0; j < m-1;j++) { 65 | if(contains[start][j]) { 66 | if(mask[j] == 0) counter++; 67 | mask[j]++; 68 | } 69 | } 70 | 71 | while(counter == m-1) { 72 | best = min(best,start-end+1); 73 | for(int j = 0; j < m-1;j++) { 74 | if(contains[end][j]) { 75 | mask[j]--; 76 | if(mask[j] == 0) counter--; 77 | } 78 | } 79 | end++; 80 | } 81 | } 82 | 83 | cout << best << "\n"; 84 | } 85 | 86 | signed main() { 87 | ios_base::sync_with_stdio(false); 88 | cin.tie(0); 89 | 90 | int t; 91 | cin >> t; 92 | 93 | while(t--) 94 | solve(); 95 | } 96 | -------------------------------------------------------------------------------- /week4/Hit.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define int long 5 | 6 | using namespace std; 7 | 8 | typedef CGAL::Exact_predicates_inexact_constructions_kernel K; 9 | 10 | typedef CGAL::Point_2 Point; 11 | typedef CGAL::Segment_2 Segment; 12 | typedef CGAL::Ray_2 Ray; 13 | 14 | void solve(int n) { 15 | int x,y,a,b; 16 | cin >> x >> y >> a >> b; 17 | 18 | Ray ray = Ray(Point(x,y),Point(a,b)); 19 | 20 | vector segments(n); 21 | for(int i = 0; i < n;i++) { 22 | int r,s,t,u; 23 | cin >> r >> s >> t >> u; 24 | segments[i] = Segment(Point(r,s),Point(t,u)); 25 | } 26 | 27 | random_shuffle(segments.begin(),segments.end()); 28 | 29 | bool hit = false; 30 | 31 | for(auto seg: segments) { 32 | if(CGAL::do_intersect(seg,ray)) { 33 | hit = true; 34 | break; 35 | } 36 | } 37 | 38 | cout << ((hit) ? "yes" : "no") << endl; 39 | } 40 | 41 | signed main() { 42 | ios_base::sync_with_stdio(false); 43 | cin.tie(0); 44 | 45 | int n; 46 | cin >> n; 47 | 48 | while(n != 0) { 49 | solve(n); 50 | cin >> n; 51 | } 52 | 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /week5/Asterix the Gaul.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define int long 4 | 5 | using namespace std; 6 | 7 | struct Move { 8 | int d; 9 | int t; 10 | bool operator<(const Move &other) const { 11 | return this->t < other.t; 12 | } 13 | }; 14 | 15 | int n,m,D,T; 16 | vector moves; 17 | 18 | void generate(vector &curr, int from, int to, int boost, Move move) { 19 | if(move.t >= T) return; 20 | if(from == to) { 21 | curr.push_back(move); 22 | return; 23 | } 24 | 25 | generate(curr,from+1,to,boost,move); 26 | generate(curr,from+1,to,boost,{move.d + moves[from].d + boost, move.t + moves[from].t}); 27 | } 28 | 29 | bool compute(int boost) { 30 | vector moves1(0); generate(moves1, 0,n/2,boost,Move{0,0}); 31 | vector moves2(0); generate(moves2, n/2,n,boost,Move{0,0}); 32 | 33 | sort(moves1.begin(),moves1.end()); 34 | sort(moves2.begin(),moves2.end()); 35 | 36 | for(int i = 1; i < moves1.size(); i++) moves1[i].d = max(moves1[i].d,moves1[i-1].d); 37 | for(int i = 1; i < moves2.size(); i++) moves2[i].d = max(moves2[i].d,moves2[i-1].d); 38 | 39 | for(auto mv1 : moves1) { 40 | auto mv2 = lower_bound(moves2.begin(),moves2.end(),T - mv1.t,[](Move m,int t){ 41 | return m.t < t; 42 | }) - 1; 43 | if(mv2->d + mv1.d >= D) 44 | return true; 45 | } 46 | 47 | return false; 48 | } 49 | 50 | void solve() { 51 | 52 | cin >> n >> m >> D >> T; 53 | 54 | moves = vector(n); 55 | for(int i = 0; i < n;i++) { 56 | int d,t; 57 | cin >> d >> t; 58 | moves[i] = {d,t}; 59 | } 60 | 61 | vector boost(m+2,0); 62 | for(int i = 1; i <= m;i++) { 63 | cin >> boost[i]; 64 | } 65 | 66 | int start = 0; 67 | int end = m+1; 68 | 69 | while(start != end) { 70 | int middle = (start + end) / 2; 71 | if(compute(boost[middle])) { 72 | end = middle; 73 | } else { 74 | start = middle + 1; 75 | } 76 | } 77 | 78 | if(start == m+1) { 79 | cout << "Panoramix captured" << "\n"; 80 | } else { 81 | cout << start << "\n"; 82 | } 83 | } 84 | 85 | signed main() { 86 | ios_base::sync_with_stdio(false); 87 | cin.tie(0); 88 | 89 | int t; 90 | cin >> t; 91 | 92 | while(t--) 93 | solve(); 94 | } 95 | -------------------------------------------------------------------------------- /week5/Boats.cpp: -------------------------------------------------------------------------------- 1 | ///1 2 | #include 3 | 4 | #define int long 5 | 6 | using namespace std; 7 | 8 | struct Boat { 9 | int position; 10 | int length; 11 | }; 12 | 13 | void solve() { 14 | int n; 15 | cin >> n; 16 | 17 | vector boats(n); 18 | for(int i = 0; i < n;i++) { 19 | cin >> boats[i].length; 20 | cin >> boats[i].position; 21 | } 22 | 23 | sort(boats.begin(),boats.end(), [](auto b1,auto b2) { 24 | return b1.position < b2.position; 25 | }); 26 | 27 | int max_score = 0; 28 | int last_position = INT_MIN; 29 | 30 | int idx = 0; 31 | 32 | while(idx < n) { 33 | 34 | int best_score = INT_MAX; 35 | 36 | while(idx < n) { 37 | int position = boats[idx].position; 38 | int length = boats[idx].length; 39 | 40 | if(position >= best_score) break; 41 | 42 | best_score = min(best_score,max(last_position,position-length) + length); 43 | idx++; 44 | } 45 | 46 | max_score++; 47 | last_position = best_score; 48 | } 49 | 50 | cout << max_score << "\n"; 51 | } 52 | 53 | signed main() { 54 | 55 | ios_base::sync_with_stdio(false); 56 | cin.tie(0); 57 | 58 | int t; 59 | cin >> t; 60 | 61 | while(t--) 62 | solve(); 63 | } 64 | -------------------------------------------------------------------------------- /week5/Moving Books.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define int long long 6 | 7 | using namespace std; 8 | 9 | void solve() { 10 | 11 | int n,m; 12 | cin >> n >> m; 13 | 14 | vector s(n); 15 | vector w(m); 16 | 17 | for(int i = 0; i < n;i++) { 18 | cin >> s[i]; 19 | } 20 | 21 | for(int j = 0; j < m;j++) { 22 | cin >> w[j]; 23 | } 24 | 25 | sort(s.begin(),s.end(),greater()); 26 | sort(w.begin(),w.end(),greater()); 27 | 28 | if(s[0]< w[0]) { 29 | cout << "impossible\n"; 30 | return; 31 | } 32 | 33 | // Nb of boxes per personns 34 | vector num_boxes(n,0); 35 | int max_box = 1; 36 | 37 | // First person takes the first box (greedy choice) 38 | num_boxes[0]++; 39 | 40 | // Then we iteratively add boxes 41 | for(int i = 1; i < m; i++) { 42 | 43 | // Check which persons can take this box 44 | int next_person = upper_bound(num_boxes.begin(),num_boxes.end(),max_box,greater()) - num_boxes.begin(); 45 | 46 | // Until is the index at which people become too weak to wear the boxes 47 | int until = upper_bound(s.begin(),s.end(),w[i],greater()) - s.begin(); 48 | 49 | // If the next person is too weak ==> increase capacity : else take it 50 | if(next_person < until) { 51 | num_boxes[next_person]++; 52 | } else { 53 | num_boxes[0]++; 54 | max_box++; 55 | } 56 | } 57 | 58 | // Print the result 59 | cout << (max_box - 1) * 3 + 2 << endl; 60 | } 61 | 62 | signed main() { 63 | 64 | ios_base::sync_with_stdio(false); 65 | cin.tie(NULL); 66 | 67 | int t; 68 | cin >> t; 69 | 70 | while(t--) 71 | solve(); 72 | 73 | return 0; 74 | } 75 | -------------------------------------------------------------------------------- /week5/Severus Snape.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define int long 4 | 5 | using namespace std; 6 | 7 | int n,m,a,b,P,W,H; 8 | vector> A; 9 | vector B; 10 | 11 | vector> compute() { 12 | 13 | vector> dp(n+1,vector(H+1,0)); 14 | vector> dp_next = dp; 15 | 16 | for(int i = 0; i < n;i++) { 17 | for(int k = 1; k <= n;k++) { 18 | for(int h = 0; h <= H;h++) { 19 | if(h - A[i].second > 0 && dp[k-1][h - A[i].second] == 0) { 20 | dp_next[k][h] = dp[k][h]; 21 | } 22 | else { 23 | dp_next[k][h] = max(dp[k][h],dp[k-1][max(h - A[i].second,0L)] + A[i].first); 24 | } 25 | } 26 | } 27 | dp = dp_next; 28 | } 29 | 30 | 31 | return dp; 32 | } 33 | 34 | void solve() { 35 | cin >> n >> m >> a >> b >> P >> H >> W; 36 | 37 | A = vector>(n); 38 | B = vector(m); 39 | 40 | for(int i = 0; i < n;i++) { 41 | int p,h;cin >> p >> h; 42 | A[i] = make_pair(p,h); 43 | } 44 | 45 | for(int i = 0; i < m;i++) { 46 | cin >> B[i]; 47 | } 48 | 49 | sort(B.begin(),B.end(),greater()); 50 | 51 | int ans = LONG_MAX; 52 | vector> dp = compute(); 53 | 54 | for(int i = 0; i <= m;i++) { 55 | int W_tmp = 0,P_tmp = 0,H_tmp = 0; 56 | 57 | for(int idx = 0; idx < i;idx++) { 58 | W_tmp += B[idx]; 59 | } 60 | 61 | int j = 0; 62 | while(j < n && (P_tmp < (P + i*b) || H_tmp < H)) { 63 | P_tmp = dp[j+1][H]; 64 | H_tmp = H; 65 | j++; 66 | } 67 | 68 | if(P_tmp >= (P + i*b) && W_tmp >= (W + j*a) && H_tmp >= H) { 69 | ans = min(ans,i + j); 70 | } 71 | } 72 | 73 | ans = (ans == LONG_MAX) ? -1 : ans; 74 | 75 | cout << ans << "\n"; 76 | 77 | return; 78 | } 79 | 80 | signed main() { 81 | ios_base::sync_with_stdio(false); 82 | cin.tie(0); 83 | 84 | int t; 85 | cin >> t; 86 | 87 | while(t--) 88 | solve(); 89 | 90 | return 0; 91 | } 92 | -------------------------------------------------------------------------------- /week6/Diet.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | typedef int IT; 8 | typedef CGAL::Gmpz ET; 9 | 10 | typedef CGAL::Quadratic_program Program; 11 | typedef CGAL::Quadratic_program_solution Solution; 12 | 13 | using namespace std; 14 | 15 | signed main() { 16 | int n,m; 17 | cin >> n >> m; 18 | 19 | while(n != 0) { 20 | 21 | vector> nutriments(n); 22 | for(int i = 0; i < n;i++) { 23 | int nut_min,nut_max; 24 | cin >> nut_min >> nut_max; 25 | nutriments[i] = make_pair(nut_min,nut_max); 26 | } 27 | 28 | vector prices(m); 29 | vector> values(m,vector(n)); 30 | for(int j = 0;j < m;j++) { 31 | cin >> prices[j]; 32 | for(int i = 0; i < n;i++) { 33 | cin >> values[j][i]; 34 | } 35 | } 36 | 37 | Program lp(CGAL::SMALLER, true, 0, false, 0); 38 | 39 | for(int i = 0; i < n;i++) { 40 | for(int j = 0; j < m;j++) { 41 | lp.set_a(j,2*i,values[j][i]); 42 | lp.set_a(j,2*i+1,-values[j][i]); 43 | } 44 | lp.set_b(2*i,nutriments[i].second); 45 | lp.set_b(2*i+1,-nutriments[i].first); 46 | } 47 | 48 | for(int j = 0; j < m;j++) { 49 | lp.set_c(j,prices[j]); 50 | } 51 | 52 | Solution s = CGAL::solve_linear_program(lp,ET()); 53 | 54 | if(s.is_infeasible()) { 55 | cout << "No such diet." << "\n"; 56 | } 57 | else { 58 | cout << floor(CGAL::to_double(s.objective_value())) << endl; 59 | } 60 | 61 | cin >> n >> m; 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /week6/Inball.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | typedef int IT; 8 | typedef CGAL::Gmpz ET; 9 | 10 | typedef CGAL::Quadratic_program Program; 11 | typedef CGAL::Quadratic_program_solution Solution; 12 | 13 | using namespace std; 14 | 15 | int main() { 16 | 17 | int n,d,a,b; 18 | cin >> n; 19 | 20 | while(n != 0) { 21 | 22 | cin >> d; 23 | 24 | Program lp = Program(CGAL::SMALLER, false, 0, false, 0); 25 | 26 | for(int i = 0; i < n;i++) { 27 | int norm = 0; 28 | for(int j = 0;j < d;j++) { 29 | cin >> a; 30 | norm += a * a; 31 | lp.set_a(j,i,a); 32 | } 33 | lp.set_a(d,i,sqrt(norm)); 34 | cin >> b; 35 | lp.set_b(i,b); 36 | } 37 | 38 | lp.set_l(d,true,0); 39 | lp.set_c(d,-1); 40 | 41 | Solution s = CGAL::solve_linear_program(lp, ET()); 42 | 43 | if(s.is_infeasible()) { 44 | cout << "none" << "\n"; 45 | } else if(s.is_unbounded()) { 46 | cout << "inf" << "\n"; 47 | } else { 48 | cout << -s.objective_value_numerator() / s.objective_value_denominator() << "\n"; 49 | } 50 | 51 | cin >> n; 52 | } 53 | 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /week6/Maximize it!.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | typedef int IT; 9 | typedef CGAL::Gmpz ET; 10 | 11 | typedef CGAL::Quadratic_program Program; 12 | typedef CGAL::Quadratic_program_solution Solution; 13 | 14 | const int X = 0; 15 | const int Y = 1; 16 | const int Z = 2; 17 | 18 | int main() { 19 | 20 | while (true) { 21 | int p,a,b; 22 | cin >> p >> a >> b; 23 | 24 | if(p == 0) { 25 | return 0; 26 | } 27 | if(p == 1) { 28 | Program lp(CGAL::SMALLER, true, 0, false, 0); 29 | 30 | lp.set_a(X,0,1); lp.set_a(Y,0,1); lp.set_b(0,4); 31 | lp.set_a(X,1,4); lp.set_a(Y,1,2); lp.set_b(1,a*b); 32 | lp.set_a(X,2,-1); lp.set_a(Y,2,1); lp.set_b (2,1); 33 | 34 | lp.set_c(X,a); lp.set_c(Y,-b); 35 | 36 | Solution s = CGAL::solve_linear_program(lp,ET()); 37 | 38 | if(s.is_infeasible()) { 39 | cout << "no" << "\n"; 40 | } else if(s.is_unbounded()) { 41 | cout << "unbounded" << "\n"; 42 | } else { 43 | cout << floor(CGAL::to_double(-s.objective_value())) << endl; 44 | } 45 | } 46 | if(p == 2) { 47 | Program lp(CGAL::SMALLER, false, 0, true, 0); 48 | 49 | lp.set_a(X,0,-1); lp.set_a(Y,0,-1); lp.set_a(Z,0,0);lp.set_b(0,4); 50 | lp.set_a(X,1,-4); lp.set_a(Y,1,-2); lp.set_a(Z,1,-1);lp.set_b(1,a*b); 51 | lp.set_a(X,2,1); lp.set_a(Y,2,-1); lp.set_a(Z,2,0);lp.set_b(2,1); 52 | 53 | lp.set_c(X,a); lp.set_c(Y,b); lp.set_c(Z,1); 54 | 55 | Solution s = CGAL::solve_linear_program(lp,ET()); 56 | 57 | if(s.is_infeasible()) { 58 | cout << "no" << "\n"; 59 | } else if(s.is_unbounded()) { 60 | cout << "unbounded" << "\n"; 61 | } else { 62 | cout << ceil(CGAL::to_double(s.objective_value())) << endl; 63 | } 64 | } 65 | } 66 | 67 | return 0; 68 | } 69 | -------------------------------------------------------------------------------- /week6/Suez.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #define int long 8 | 9 | typedef int IT; 10 | typedef CGAL::Gmpz ET; 11 | 12 | typedef CGAL::Quadratic_program Program; 13 | typedef CGAL::Quadratic_program_solution Solution; 14 | 15 | typedef CGAL::Quotient Fraction; 16 | 17 | using namespace std; 18 | 19 | void solve() { 20 | 21 | int n,m,h,w; 22 | cin >> n >> m >> h >> w; 23 | 24 | vector> positions(n); 25 | vector> hanging(m); 26 | 27 | for(int i = 0; i < n;i++) { 28 | int x,y; 29 | cin >> x >> y; 30 | positions[i] = make_pair(x,y); 31 | } 32 | 33 | for(int j = 0; j < m;j++) { 34 | int x,y; 35 | cin >> x >> y; 36 | hanging[j] = make_pair(x,y); 37 | } 38 | 39 | Program lp = Program(CGAL::SMALLER, true, 1, false, 0); 40 | int equation = 0; 41 | 42 | for(int i = 0; i < n;i++) { 43 | Fraction fraction(1,0); 44 | for(int j = 0; j < m;j++) { 45 | int cx = 2*abs(positions[i].first - hanging[j].first) - w; 46 | int cy = 2*abs(positions[i].second - hanging[j].second) - h; 47 | Fraction other; 48 | if(cx*h >= cy*w) other = {cx,w}; 49 | else other = {cy,h}; 50 | if(fraction.denominator() == 0 || other < fraction) 51 | fraction = other; 52 | } 53 | lp.set_a(i,equation,fraction.denominator()); 54 | lp.set_b(equation,fraction.numerator()); 55 | equation++; 56 | } 57 | 58 | for(int i = 0; i < n;i++) { 59 | for(int j = i+1; j < n;j++) { 60 | int cx = 2*abs(positions[i].first - positions[j].first); 61 | int cy = 2*abs(positions[i].second - positions[j].second); 62 | if(cx*h >= cy*w) { 63 | lp.set_a(i,equation,w); 64 | lp.set_a(j,equation,w); 65 | lp.set_b(equation,cx); 66 | } 67 | else { 68 | lp.set_a(i,equation,h); 69 | lp.set_a(j,equation,h); 70 | lp.set_b(equation,cy); 71 | } 72 | equation++; 73 | } 74 | } 75 | 76 | for(int i = 0; i < n;i++) { 77 | lp.set_c(i, -2*(h + w)); 78 | } 79 | 80 | Solution s = CGAL::solve_linear_program(lp,ET()); 81 | 82 | int numerator = abs(s.objective_value().numerator().to_double()); 83 | int denominator = abs(s.objective_value().denominator().to_double()); 84 | 85 | int solution = numerator / denominator; 86 | int rest = numerator % denominator; 87 | if(rest > 0) solution++; 88 | 89 | cout << solution << "\n"; 90 | 91 | return; 92 | } 93 | 94 | signed main() { 95 | 96 | int t; 97 | cin >> t; 98 | 99 | while(t--) 100 | solve(); 101 | 102 | return 0; 103 | } 104 | -------------------------------------------------------------------------------- /week7/Coin Tossing Tournament.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | #define int long 11 | 12 | typedef boost::adjacency_list_traits traits; 13 | typedef boost::adjacency_list>>> graph; 17 | 18 | typedef traits::vertex_descriptor vertex_desc; 19 | typedef traits::edge_descriptor edge_desc; 20 | 21 | class edge_adder { 22 | 23 | graph &G; 24 | 25 | public: 26 | explicit edge_adder(graph &G) : G(G) {} 27 | 28 | void add_edge(int from, int to, int weight) { 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] = weight; 34 | c_map[rev_e] = 0; 35 | r_map[e] = rev_e; 36 | r_map[rev_e] = e; 37 | } 38 | }; 39 | 40 | void solve() { 41 | 42 | int n,m; 43 | cin >> n >> m; 44 | 45 | vector> players(m); 46 | vector outcomes(m); 47 | vector scores(n); 48 | 49 | for(int i = 0; i < m;i ++) { 50 | int a,b; 51 | cin >> a >> b; 52 | players[i] = make_pair(a,b); 53 | cin >> outcomes[i]; 54 | } 55 | 56 | for(int i = 0; i < n;i++) { 57 | cin >> scores[i]; 58 | } 59 | 60 | if(accumulate(scores.begin(),scores.end(),0) != m) { 61 | cout << "no" << "\n"; 62 | return; 63 | } 64 | 65 | graph G(n + m); 66 | edge_adder adder(G); 67 | 68 | const vertex_desc v_source = boost::add_vertex(G); 69 | const vertex_desc v_sink = boost::add_vertex(G); 70 | 71 | for(int i = 0; i < m;i++) { 72 | if(outcomes[i] == 0) { 73 | adder.add_edge(i,m + players[i].first,1); 74 | adder.add_edge(i,m + players[i].second,1); 75 | } 76 | else if(outcomes[i] == 1) { 77 | scores[players[i].first]--; 78 | if(scores[players[i].first] < 0) { 79 | cout << "no" << "\n"; 80 | return; 81 | } 82 | } 83 | else if(outcomes[i] == 2) { 84 | scores[players[i].second]--; 85 | if(scores[players[i].second] < 0) { 86 | cout << "no" << "\n"; 87 | return; 88 | } 89 | } 90 | } 91 | 92 | for(int i = 0; i < m;i++) { 93 | adder.add_edge(v_source, i ,1); 94 | } 95 | 96 | for(int i = 0; i < n;i++) { 97 | adder.add_edge(m + i, v_sink, scores[i]); 98 | } 99 | 100 | long flow = boost::push_relabel_max_flow(G, v_source, v_sink); 101 | long value = accumulate(scores.begin(),scores.end(),0); 102 | 103 | cout << ((flow == value) ? "yes" : "no") << "\n"; 104 | 105 | return; 106 | } 107 | 108 | signed main() { 109 | 110 | int t; 111 | cin >> t; 112 | 113 | while(t--) 114 | solve(); 115 | } 116 | -------------------------------------------------------------------------------- /week7/London.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #define int long 7 | 8 | using namespace std; 9 | 10 | typedef boost::adjacency_list_traits traits; 11 | typedef boost::adjacency_list>>> graph; 15 | 16 | typedef traits::vertex_descriptor vertex_desc; 17 | typedef traits::edge_descriptor edge_desc; 18 | 19 | class edge_adder { 20 | 21 | graph &G; 22 | 23 | public: 24 | explicit edge_adder(graph &G) : G(G) {} 25 | 26 | void add_edge(int from, int to,int capacity) { 27 | auto c_map = boost::get(boost::edge_capacity, G); 28 | auto r_map = boost::get(boost::edge_reverse, G); 29 | const auto e = boost::add_edge(from, to, G).first; 30 | const auto rev_e = boost::add_edge(to, from, G).first; 31 | c_map[e] = capacity; 32 | c_map[rev_e] = 0; 33 | r_map[e] = rev_e; 34 | r_map[rev_e] = e; 35 | } 36 | }; 37 | 38 | void solve() { 39 | int h,w; 40 | cin >> h >> w; 41 | 42 | string s; 43 | cin >> s; 44 | 45 | vector count(26,0); 46 | for(int i = 0; i < s.size();i++) { 47 | count[s[i] - 'A']++; 48 | } 49 | 50 | vector sfront(h); 51 | vector sback(h); 52 | 53 | for(int i = 0; i < h;i++) { 54 | cin >> sfront[i]; 55 | } 56 | for(int i = 0; i < h;i++) { 57 | cin >> sback[i]; 58 | } 59 | 60 | vector> matrix(26,vector(26,0)); 61 | 62 | for(int i = 0; i < h;i++) { 63 | for(int j = 0; j < w;j++) { 64 | matrix[sfront[i][j] - 'A'][sback[i][w - j - 1] - 'A']++; 65 | } 66 | } 67 | 68 | graph G(26*26 + 26); 69 | edge_adder adder(G); 70 | 71 | auto v_source = boost::add_vertex(G); 72 | auto v_sink = boost::add_vertex(G); 73 | 74 | for(int i = 0; i < 26;i++) { 75 | for(int j = 0; j < 26;j++) { 76 | adder.add_edge(v_source,26*i + j, matrix[i][j]); 77 | adder.add_edge(26*i + j, 26*26 + i,INT_MAX); 78 | adder.add_edge(26*i + j, 26*26 + j,INT_MAX); 79 | } 80 | } 81 | 82 | for(int k = 0; k < 26; k++) { 83 | adder.add_edge(26*26 + k, v_sink, count[k]); 84 | } 85 | 86 | long flow = boost::push_relabel_max_flow(G,v_source,v_sink); 87 | 88 | if(flow == s.size()) { 89 | cout << "Yes" << "\n"; 90 | } else { 91 | cout << "No" << "\n"; 92 | } 93 | } 94 | 95 | signed main() { 96 | ios_base::sync_with_stdio(false); 97 | cin.tie(0); 98 | 99 | int t; 100 | cin >> t; 101 | 102 | while(t--) 103 | solve(); 104 | } 105 | -------------------------------------------------------------------------------- /week7/Shopping Trip.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | typedef boost::adjacency_list_traits traits; 10 | typedef boost::adjacency_list>>> graph; 14 | 15 | typedef traits::vertex_descriptor vertex_desc; 16 | typedef traits::edge_descriptor edge_desc; 17 | 18 | class edge_adder { 19 | 20 | graph &G; 21 | 22 | public: 23 | explicit edge_adder(graph &G) : G(G) {} 24 | 25 | void add_edge(int from, int to) { 26 | auto c_map = boost::get(boost::edge_capacity, G); 27 | auto r_map = boost::get(boost::edge_reverse, G); 28 | const auto e = boost::add_edge(from, to, G).first; 29 | const auto rev_e = boost::add_edge(to, from, G).first; 30 | c_map[e] = 1; 31 | c_map[rev_e] = 1; 32 | r_map[e] = rev_e; 33 | r_map[rev_e] = e; 34 | } 35 | }; 36 | 37 | void solve() { 38 | 39 | int n,m,s; 40 | cin >> n >> m >> s; 41 | 42 | graph G(n); 43 | edge_adder adder(G); 44 | 45 | const vertex_desc v_sink = boost::add_vertex(G); 46 | const int v_source = 0; 47 | 48 | for(int i = 0; i < s;i++) { 49 | int store; cin >> store; 50 | adder.add_edge(store,v_sink); 51 | } 52 | 53 | for(int i = 0; i < m;i++) { 54 | int part1,part2; 55 | cin >> part1 >> part2; 56 | adder.add_edge(part1,part2); 57 | } 58 | 59 | long flow = boost::push_relabel_max_flow(G, v_source, v_sink); 60 | 61 | cout << ((flow == s) ? "yes" : "no") << "\n"; 62 | 63 | return; 64 | } 65 | 66 | int main() { 67 | 68 | int t; 69 | cin >> t; 70 | 71 | while(t--) 72 | solve(); 73 | } 74 | -------------------------------------------------------------------------------- /week7/Tiles.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | typedef boost::adjacency_list_traits traits; 10 | typedef boost::adjacency_list>>> graph; 14 | 15 | typedef traits::vertex_descriptor vertex_desc; 16 | typedef traits::edge_descriptor edge_desc; 17 | 18 | class edge_adder { 19 | 20 | graph &G; 21 | 22 | public: 23 | explicit edge_adder(graph &G) : G(G) {} 24 | 25 | void add_edge(int from, int to) { 26 | auto c_map = boost::get(boost::edge_capacity, G); 27 | auto r_map = boost::get(boost::edge_reverse, G); 28 | const auto e = boost::add_edge(from, to, G).first; 29 | const auto rev_e = boost::add_edge(to, from, G).first; 30 | c_map[e] = 1; 31 | c_map[rev_e] = 0; 32 | r_map[e] = rev_e; 33 | r_map[rev_e] = e; 34 | } 35 | 36 | }; 37 | 38 | int w,h; 39 | 40 | int flatten(int i, int j) { 41 | return i * w + j; 42 | } 43 | 44 | 45 | void solve() { 46 | 47 | cin >> w >> h; 48 | 49 | vector grid(h); 50 | 51 | for(int i = 0; i < h;i++) { 52 | cin >> grid[i]; 53 | } 54 | 55 | graph G(w*h); 56 | edge_adder adder(G); 57 | 58 | vertex_desc v_source = boost::add_vertex(G); 59 | vertex_desc v_sink = boost::add_vertex(G); 60 | 61 | int counter = 0; 62 | 63 | for(int i = 0; i < h;i++) { 64 | for(int j = 0; j < w;j++) { 65 | 66 | if(grid[i][j] == 'x') continue; 67 | 68 | counter++; 69 | 70 | if((i + j) % 2 == 0) { 71 | adder.add_edge(v_source,flatten(i,j)); 72 | if(i > 0) adder.add_edge(flatten(i,j),flatten(i-1,j)); 73 | if(i < h-1) adder.add_edge(flatten(i,j),flatten(i+1,j)); 74 | if(j > 0) adder.add_edge(flatten(i,j),flatten(i,j-1)); 75 | if(j < w-1) adder.add_edge(flatten(i,j),flatten(i,j+1)); 76 | } 77 | else { 78 | adder.add_edge(flatten(i,j),v_sink); 79 | } 80 | } 81 | } 82 | 83 | int flow = boost::push_relabel_max_flow(G, v_source, v_sink); 84 | 85 | if(2*flow == counter) { 86 | cout << "yes" << "\n"; 87 | } 88 | else { 89 | cout << "no" << "\n"; 90 | } 91 | 92 | return; 93 | } 94 | 95 | signed main() { 96 | 97 | int t; 98 | cin >> t; 99 | 100 | while(t--) 101 | solve(); 102 | } 103 | -------------------------------------------------------------------------------- /week8/Bistro.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | typedef CGAL::Exact_predicates_inexact_constructions_kernel K; 8 | typedef CGAL::Delaunay_triangulation_2 Triangulation; 9 | typedef CGAL::Point_2 Point_2; 10 | typedef Triangulation::Finite_faces_iterator Face_iterator; 11 | 12 | using namespace std; 13 | 14 | void solve(int n) { 15 | 16 | vector points; 17 | points.reserve(n); 18 | for(int i = 0; i < n;i++) { 19 | int x,y; 20 | cin >> x >> y; 21 | points.push_back(Point_2(x,y)); 22 | } 23 | 24 | Triangulation t; 25 | t.insert(points.begin(),points.end()); 26 | 27 | int m; cin >> m; 28 | 29 | for(int i = 0; i < m;i++) { 30 | int x,y; 31 | cin >> x >> y; 32 | Point_2 new_restaurant(x,y); 33 | Point_2 nearest_restaurant = t.nearest_vertex(new_restaurant)->point(); 34 | 35 | cout << long(squared_distance(new_restaurant,nearest_restaurant)) << "\n"; 36 | } 37 | 38 | return; 39 | } 40 | 41 | signed main() { 42 | 43 | int n; 44 | cin >> n; 45 | while(n != 0) { 46 | solve(n); 47 | cin >> n; 48 | } 49 | 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /week8/Germs.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | typedef CGAL::Exact_predicates_inexact_constructions_kernel K; 8 | typedef CGAL::Point_2 Point; 9 | typedef CGAL::Delaunay_triangulation_2 Triangulation; 10 | typedef Triangulation::Vertex_iterator Vertex_iterator; 11 | 12 | using namespace std; 13 | 14 | // Given the distance ==> Say how long it takes before it collides 15 | inline double transform(double distance) { 16 | return sqrt((sqrt(distance) - 1) / 2); 17 | } 18 | 19 | void solve(int n) { 20 | int left, bottom, right, top; 21 | cin >> left >> bottom >> right >> top; 22 | 23 | vector points(n); 24 | for(int i = 0; i < n;i++) { 25 | int x,y; 26 | cin >> x >> y; 27 | points[i] = Point(x,y); 28 | } 29 | 30 | Triangulation t; 31 | t.insert(points.begin(),points.end()); 32 | 33 | vector distances; 34 | distances.reserve(n); 35 | 36 | for(Vertex_iterator vertex_it = t.finite_vertices_begin(); vertex_it != t.finite_vertices_end(); ++vertex_it) { 37 | 38 | double x = vertex_it->point().x(); 39 | double y = vertex_it->point().y(); 40 | 41 | double min_distance = sqrt(std::min({abs(left - x),abs(right - x),abs(bottom - y),abs(top - y)}) - 0.5); 42 | 43 | auto c = t.incident_edges(vertex_it); 44 | if(c != 0) { 45 | do { 46 | if(t.is_infinite(c)) continue; 47 | min_distance = min(min_distance,transform(t.segment(c).squared_length())); 48 | } while(++c != t.incident_edges(vertex_it)); 49 | } 50 | 51 | distances.push_back(min_distance); 52 | } 53 | 54 | sort(distances.begin(),distances.end()); 55 | 56 | cout << ceil(distances[0]) << " " << ceil(distances[n/2]) << " " << ceil(distances.back()) << "\n"; 57 | 58 | return; 59 | } 60 | 61 | sined main() { 62 | ios_base::sync_with_stdio(false); 63 | cin.tie(0); 64 | 65 | int n; 66 | cin >> n; 67 | 68 | while(n != 0) { 69 | solve(n); 70 | cin >> n; 71 | } 72 | 73 | return 0; 74 | } 75 | -------------------------------------------------------------------------------- /week8/H1N1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | typedef CGAL::Exact_predicates_inexact_constructions_kernel K; 8 | typedef CGAL::Triangulation_vertex_base_2 Vb; 9 | typedef CGAL::Triangulation_face_base_with_info_2 Fb; 10 | typedef CGAL::Triangulation_data_structure_2 Tds; 11 | typedef CGAL::Delaunay_triangulation_2 Triangulation; 12 | 13 | typedef CGAL::Point_2 Point; 14 | 15 | using namespace std; 16 | 17 | void solve(int n) { 18 | 19 | vector points(n); 20 | for(int i = 0; i < n;i++) { 21 | int x,y; 22 | cin >> x >> y; 23 | points[i] = Point(x,y); 24 | } 25 | 26 | Triangulation t; 27 | t.insert(points.begin(),points.end()); 28 | 29 | unsigned int nb_faces = 1; 30 | for(auto f = t.finite_faces_begin(); f != t.finite_faces_end(); ++f) { 31 | f->info() = nb_faces++; 32 | } 33 | 34 | vector>> edges(nb_faces); 35 | for(auto f = t.finite_faces_begin(); f != t.finite_faces_end();++ f) { 36 | int u = f->info(); 37 | 38 | for(int i = 0; i < 3;i++) { 39 | auto f2 = f->neighbor(i); 40 | int v = t.is_infinite(f2) ? 0 : f2->info(); 41 | 42 | auto p1 = f->vertex((i + 1) % 3)->point(); 43 | auto p2 = f->vertex((i + 2) % 3)->point(); 44 | 45 | double dist = CGAL::squared_distance(p1,p2); 46 | edges[u].push_back({v, dist}); 47 | if(v == 0) { 48 | edges[v].push_back({u, dist}); 49 | } 50 | } 51 | } 52 | 53 | vector bottleneck(nb_faces, -1); 54 | 55 | priority_queue> Q; 56 | Q.push({std::numeric_limits::max(), 0}); 57 | 58 | while(!Q.empty()) { 59 | 60 | auto p = Q.top(); Q.pop(); 61 | 62 | double val = p.first; 63 | int u = p.second; 64 | 65 | if(bottleneck[u] != -1) { 66 | continue; 67 | } 68 | 69 | bottleneck[u] = val; 70 | 71 | for(auto next : edges[u]) { 72 | double dist = next.second; 73 | int v = next.first; 74 | if(bottleneck[v] == -1) Q.push({min(dist,val),v}); 75 | } 76 | 77 | } 78 | 79 | int m; 80 | cin >> m; 81 | 82 | for(int i = 0; i < m;i++) { 83 | int x,y; 84 | double d; 85 | cin >> x >> y >> d; 86 | auto p = Point(x,y); 87 | double dist = CGAL::squared_distance(p, t.nearest_vertex(p)->point()); 88 | 89 | if(d > dist) { 90 | cout << "n"; 91 | continue; 92 | } 93 | 94 | auto f = t.locate(p); 95 | auto idx = t.is_infinite(f) ? 0 : f->info(); 96 | 97 | if(4*d > bottleneck[idx]) { 98 | cout << "n"; 99 | } 100 | else { 101 | cout << "y"; 102 | } 103 | 104 | } 105 | cout << "\n"; 106 | return; 107 | } 108 | 109 | int main() { 110 | 111 | ios_base::sync_with_stdio(false); 112 | cin.tie(0); 113 | 114 | int n; 115 | cin >> n; 116 | 117 | while(n != 0) { 118 | solve(n); 119 | cin >> n; 120 | } 121 | 122 | return 0; 123 | } 124 | -------------------------------------------------------------------------------- /week8/Light the Stage.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | typedef CGAL::Exact_predicates_inexact_constructions_kernel K; 8 | typedef CGAL::Point_2 Point_2; 9 | typedef CGAL::Delaunay_triangulation_2 Triangulation; 10 | typedef Triangulation::Finite_faces_iterator Face_iterator; 11 | 12 | using namespace std; 13 | 14 | typedef struct Participant { 15 | Point_2 pos; 16 | int radius; 17 | int idx; 18 | } Participant; 19 | 20 | int h; 21 | int n,m; 22 | 23 | vector playersLeft(vector &participants, vector &lamps, int left,int middle) { 24 | 25 | vector output(0); 26 | 27 | Triangulation t; 28 | t.insert(lamps.begin()+left,lamps.begin()+middle); 29 | 30 | for(int i = 0; i < participants.size();i++) { 31 | Point_2 nearest_lamp = t.nearest_vertex(participants[i].pos)->point(); 32 | double distance = CGAL::squared_distance(nearest_lamp,participants[i].pos); 33 | if(distance >= pow(participants[i].radius + h,2)) { 34 | output.push_back(participants[i]); 35 | } 36 | } 37 | 38 | return output; 39 | } 40 | 41 | void solve() { 42 | 43 | cin >> m >> n; 44 | 45 | vector participants(m); 46 | for(int i = 0; i < m;i++) { 47 | int x,y,r; 48 | cin >> x >> y >> r; 49 | participants[i] = {Point_2(x,y),r,i}; 50 | } 51 | 52 | cin >> h; 53 | 54 | vector lamps(n); 55 | for(int i = 0; i < n;i++) { 56 | int x,y; 57 | cin >> x >> y; 58 | lamps[i] = Point_2(x,y); 59 | } 60 | 61 | int start = 0; 62 | int end = lamps.size(); 63 | 64 | 65 | while(start < end) { 66 | int middle = (start + end + 1) / 2; 67 | auto remainings = playersLeft(participants,lamps,start,middle); 68 | 69 | if(remainings.size() == 0) { 70 | end = middle-1; 71 | } 72 | else { 73 | start = middle; 74 | participants = remainings; 75 | } 76 | } 77 | 78 | for(auto p: participants) 79 | cout << p.idx << " "; 80 | 81 | cout << "\n"; 82 | 83 | return; 84 | } 85 | 86 | signed main() { 87 | 88 | ios_base::sync_with_stdio(false); 89 | cin.tie(0); 90 | 91 | int t; cin >> t; 92 | 93 | while(t--) 94 | solve(); 95 | 96 | return 0; 97 | } 98 | -------------------------------------------------------------------------------- /week9/Algocoon.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | typedef boost::adjacency_list_traits traits; 11 | typedef boost::adjacency_list>>> graph; 15 | 16 | typedef traits::vertex_descriptor vertex_desc; 17 | typedef traits::edge_descriptor edge_desc; 18 | 19 | class edge_adder { 20 | 21 | graph &G; 22 | 23 | public: 24 | explicit edge_adder(graph &G) : G(G) {} 25 | 26 | void add_edge(int from, int to, int weight) { 27 | auto c_map = boost::get(boost::edge_capacity, G); 28 | auto r_map = boost::get(boost::edge_reverse, G); 29 | const auto e = boost::add_edge(from, to, G).first; 30 | const auto rev_e = boost::add_edge(to, from, G).first; 31 | c_map[e] = weight; 32 | c_map[rev_e] = 0; 33 | r_map[e] = rev_e; 34 | r_map[rev_e] = e; 35 | } 36 | }; 37 | 38 | void solve() { 39 | 40 | int n,m; 41 | cin >> n >> m; 42 | 43 | graph G(n); 44 | edge_adder adder(G); 45 | 46 | for(int i = 0; i < m;i++) { 47 | int a,b,c; 48 | cin >> a >> b >> c; 49 | adder.add_edge(a,b,c); 50 | } 51 | 52 | long min_cut = LONG_MAX; 53 | 54 | for(int i = 0; i < n;i++) { 55 | long flow = boost::push_relabel_max_flow(G, 0, i); 56 | min_cut = min(min_cut,flow); 57 | 58 | flow = boost::push_relabel_max_flow(G,i, 0); 59 | min_cut = min(min_cut,flow); 60 | } 61 | 62 | cout << min_cut << "\n"; 63 | 64 | 65 | return; 66 | } 67 | 68 | signed main() { 69 | 70 | ios_base::sync_with_stdio(false); 71 | cin.tie(0); 72 | 73 | int t; 74 | cin >> t; 75 | 76 | while(t--) 77 | solve(); 78 | } 79 | -------------------------------------------------------------------------------- /week9/Casino Royale.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define int long 10 | 11 | using namespace std; 12 | 13 | typedef boost::adjacency_list_traits traits; 14 | typedef boost::adjacency_list>>>> graph; 19 | 20 | typedef boost::graph_traits::edge_descriptor edge_desc; 21 | typedef boost::graph_traits::out_edge_iterator out_edge_it; 22 | 23 | class edge_adder 24 | { 25 | graph &G; 26 | 27 | public: 28 | explicit edge_adder(graph &G) : G(G) {} 29 | void add_edge(int from, int to, long capacity, long cost) 30 | { 31 | auto c_map = boost::get(boost::edge_capacity, G); 32 | auto r_map = boost::get(boost::edge_reverse, G); 33 | auto w_map = boost::get(boost::edge_weight, G); // new! 34 | const edge_desc e = boost::add_edge(from, to, G).first; 35 | const edge_desc rev_e = boost::add_edge(to, from, G).first; 36 | c_map[e] = capacity; 37 | c_map[rev_e] = 0; // reverse edge has no capacity! 38 | r_map[e] = rev_e; 39 | r_map[rev_e] = e; 40 | w_map[e] = cost; // new assign cost 41 | w_map[rev_e] = -cost; // new negative cost 42 | } 43 | }; 44 | 45 | 46 | void solve() { 47 | int n,m,l; 48 | cin >> n >> m >> l; 49 | 50 | int max_priority = 2<<8; 51 | graph G(n); 52 | edge_adder adder(G); 53 | 54 | auto v_source = boost::add_vertex(G); 55 | auto v_sink = boost::add_vertex(G); 56 | 57 | adder.add_edge(v_source,0,l,0); 58 | adder.add_edge(n-1,v_sink,l,0); 59 | 60 | for(int i = 0; i < n-1;i++) adder.add_edge(i,i+1,l,max_priority); 61 | 62 | for(int i = 0; i < m;i++) { 63 | int x,y,q; 64 | cin >> x >> y >> q; 65 | adder.add_edge(x,y,1,max_priority * (y - x) - q); 66 | } 67 | 68 | boost::successive_shortest_path_nonnegative_weights(G, v_source, v_sink); 69 | int cost = boost::find_flow_cost(G); 70 | cout << max_priority * (n-1) * l - cost << "\n"; 71 | } 72 | 73 | signed main() { 74 | ios_base::sync_with_stdio(false); 75 | cin.tie(0); 76 | 77 | int t; 78 | cin >> t; 79 | 80 | while(t--) 81 | solve(); 82 | 83 | return 0; 84 | } 85 | -------------------------------------------------------------------------------- /week9/Placing Knights.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | typedef boost::adjacency_list_traits traits; 11 | typedef boost::adjacency_list>>> graph; 15 | 16 | typedef traits::vertex_descriptor vertex_desc; 17 | typedef traits::edge_descriptor edge_desc; 18 | 19 | vector> grid; 20 | 21 | class edge_adder { 22 | 23 | graph &G; 24 | int n; 25 | 26 | public: 27 | explicit edge_adder(graph &G, int n) : G(G), n(n) {} 28 | 29 | void add_edge(int from, int to, int weight) { 30 | auto c_map = boost::get(boost::edge_capacity, G); 31 | auto r_map = boost::get(boost::edge_reverse, G); 32 | const auto e = boost::add_edge(from, to, G).first; 33 | const auto rev_e = boost::add_edge(to, from, G).first; 34 | c_map[e] = weight; 35 | c_map[rev_e] = 0; 36 | r_map[e] = rev_e; 37 | r_map[rev_e] = e; 38 | } 39 | }; 40 | 41 | void solve() { 42 | 43 | int n; 44 | cin >> n; 45 | 46 | vector> grid = vector>(n,vector(n)); 47 | 48 | int nb_placements = 0; 49 | 50 | graph G(n*n); 51 | edge_adder adder(G,n); 52 | 53 | const vertex_desc v_source = boost::add_vertex(G); 54 | const vertex_desc v_sink = boost::add_vertex(G); 55 | 56 | vector> displacements = {{-1,-2},{-1,2},{1,-2},{1,2},{-2,-1},{-2,1},{2,-1},{2,1}}; 57 | 58 | for(int i = 0; i < n;i++) { 59 | for(int j = 0; j < n;j++) { 60 | 61 | cin >> grid[i][j]; 62 | 63 | if(grid[i][j]) { 64 | nb_placements++; 65 | if((i + j) % 2 == 0) { 66 | adder.add_edge(v_source,i*n+j,1); 67 | } 68 | else { 69 | adder.add_edge(i*n+j,v_sink,1); 70 | } 71 | } 72 | } 73 | } 74 | 75 | for(int i = 0; i < n;i++) { 76 | for(int j = 0; j < n;j++) { 77 | if(grid[i][j] && (i+j) % 2 == 0) { 78 | for(auto d : displacements) { 79 | if(i+d.first < 0 || i+d.first >= n) continue; 80 | if(j+d.second < 0 || j+d.second >= n) continue; 81 | adder.add_edge(i*n+j,(i+d.first)*n + j + d.second,1); 82 | } 83 | } 84 | } 85 | } 86 | 87 | long flow = boost::push_relabel_max_flow(G, v_source, v_sink); 88 | 89 | cout << nb_placements - flow << "\n"; 90 | 91 | return; 92 | } 93 | 94 | signed main() { 95 | 96 | int t; 97 | cin >> t; 98 | 99 | while(t--) 100 | solve(); 101 | } 102 | -------------------------------------------------------------------------------- /week9/Real Estate Market.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define int long 10 | 11 | using namespace std; 12 | 13 | typedef boost::adjacency_list_traits traits; 14 | typedef boost::adjacency_list > > > > graph; 19 | 20 | typedef boost::graph_traits::edge_descriptor edge_desc; 21 | typedef boost::graph_traits::out_edge_iterator out_edge_it; 22 | typedef traits::vertex_descriptor vertex_desc; 23 | 24 | 25 | class edge_adder { 26 | graph &G; 27 | 28 | public: 29 | explicit edge_adder(graph &G) : G(G) {} 30 | void add_edge(int from, int to, long capacity, long cost) { 31 | auto c_map = boost::get(boost::edge_capacity, G); 32 | auto r_map = boost::get(boost::edge_reverse, G); 33 | auto w_map = boost::get(boost::edge_weight, G); 34 | const edge_desc e = boost::add_edge(from, to, G).first; 35 | const edge_desc rev_e = boost::add_edge(to, from, G).first; 36 | c_map[e] = capacity; 37 | c_map[rev_e] = 0; 38 | r_map[e] = rev_e; 39 | r_map[rev_e] = e; 40 | w_map[e] = cost; 41 | w_map[rev_e] = -cost; 42 | } 43 | }; 44 | 45 | void solve() { 46 | 47 | const int NO_COST = 0; 48 | 49 | int N,M,S; 50 | cin >> N >> M >> S; 51 | 52 | vector limits(S); 53 | for(int i = 0; i < S; i++) { 54 | cin >> limits[i]; 55 | } 56 | 57 | vector group(M); 58 | for(int i = 0; i < M;i++) { 59 | cin >> group[i]; 60 | group[i]--; 61 | } 62 | 63 | vector> bets(N,vector(M,0)); 64 | 65 | int max_bet = 0; 66 | 67 | for(int i = 0; i < N;i++) { 68 | for(int j = 0; j < M;j++) { 69 | cin >> bets[i][j]; 70 | max_bet = max(max_bet,bets[i][j]); 71 | } 72 | } 73 | 74 | graph G(N + M + S); 75 | edge_adder adder(G); 76 | 77 | vertex_desc v_source = boost::add_vertex(G); 78 | vertex_desc v_sink = boost::add_vertex(G); 79 | 80 | for(int i = 0; i < N;i++) { 81 | adder.add_edge(v_source,i,1,NO_COST); 82 | } 83 | 84 | for(int i = 0; i < N;i++) { 85 | for(int j = 0; j < M;j++) { 86 | adder.add_edge(i,N + j,1,max_bet-bets[i][j]); 87 | } 88 | } 89 | 90 | for(int j = 0; j < M;j++) { 91 | adder.add_edge(N + j,N + M + group[j],1,NO_COST); 92 | } 93 | 94 | for(int i = 0; i < S;i++) { 95 | adder.add_edge(N + M + i,v_sink,limits[i],NO_COST); 96 | } 97 | 98 | int flow = boost::push_relabel_max_flow(G, v_source, v_sink); 99 | boost::successive_shortest_path_nonnegative_weights(G, v_source, v_sink); 100 | int cost = boost::find_flow_cost(G); 101 | 102 | cout << flow << " " << max_bet*flow-cost << "\n"; 103 | return; 104 | } 105 | 106 | signed main() { 107 | ios_base::sync_with_stdio(false); 108 | cin.tie(0); 109 | 110 | int t; 111 | cin >> t; 112 | 113 | while(t--) 114 | solve(); 115 | 116 | return 0; 117 | } 118 | --------------------------------------------------------------------------------