From 68cb32d0e8283c911e730380c35c2aef8fe11a90 Mon Sep 17 00:00:00 2001 From: Bernardo Panka Archegas Date: Fri, 8 Nov 2024 15:00:39 -0300 Subject: [PATCH 1/2] Added the entire dp section from cses in cpp --- cses/dp/1 - Dice Combinations.cpp | 40 +++++++++++++++ cses/dp/10 - Edit Distance.cpp | 43 ++++++++++++++++ cses/dp/11 - Rectangle Cutting.cpp | 41 +++++++++++++++ cses/dp/12 - Money Sums.cpp | 41 +++++++++++++++ cses/dp/13 - Removal game.cpp | 40 +++++++++++++++ cses/dp/14 - Two Sets II.cpp | 49 ++++++++++++++++++ cses/dp/15 - Projects.cpp | 52 +++++++++++++++++++ cses/dp/16 - Increasing Subsequence.cpp | 40 +++++++++++++++ cses/dp/17 - Elevator Rides.cpp | 46 +++++++++++++++++ cses/dp/18 - Counting Tilings.cpp | 61 +++++++++++++++++++++++ cses/dp/19 - Counting Numbers.cpp | 66 +++++++++++++++++++++++++ cses/dp/2 - Minimizing Coins.cpp | 36 ++++++++++++++ cses/dp/3 - Coin Combinations I.cpp | 41 +++++++++++++++ cses/dp/4 - Coin Combinations II.cpp | 38 ++++++++++++++ cses/dp/5 - Removing Digits.cpp | 33 +++++++++++++ cses/dp/6 - Grid Paths.cpp | 48 ++++++++++++++++++ cses/dp/7 - Book Shop.cpp | 40 +++++++++++++++ cses/dp/8 - Array Description.cpp | 45 +++++++++++++++++ cses/dp/9 - Counting Towers.cpp | 38 ++++++++++++++ 19 files changed, 838 insertions(+) create mode 100644 cses/dp/1 - Dice Combinations.cpp create mode 100644 cses/dp/10 - Edit Distance.cpp create mode 100644 cses/dp/11 - Rectangle Cutting.cpp create mode 100644 cses/dp/12 - Money Sums.cpp create mode 100644 cses/dp/13 - Removal game.cpp create mode 100644 cses/dp/14 - Two Sets II.cpp create mode 100644 cses/dp/15 - Projects.cpp create mode 100644 cses/dp/16 - Increasing Subsequence.cpp create mode 100644 cses/dp/17 - Elevator Rides.cpp create mode 100644 cses/dp/18 - Counting Tilings.cpp create mode 100644 cses/dp/19 - Counting Numbers.cpp create mode 100644 cses/dp/2 - Minimizing Coins.cpp create mode 100644 cses/dp/3 - Coin Combinations I.cpp create mode 100644 cses/dp/4 - Coin Combinations II.cpp create mode 100644 cses/dp/5 - Removing Digits.cpp create mode 100644 cses/dp/6 - Grid Paths.cpp create mode 100644 cses/dp/7 - Book Shop.cpp create mode 100644 cses/dp/8 - Array Description.cpp create mode 100644 cses/dp/9 - Counting Towers.cpp diff --git a/cses/dp/1 - Dice Combinations.cpp b/cses/dp/1 - Dice Combinations.cpp new file mode 100644 index 0000000..91db021 --- /dev/null +++ b/cses/dp/1 - Dice Combinations.cpp @@ -0,0 +1,40 @@ +// Dice Combinations +// +// Problem name: Dice Combinations +// Problem Link: https://cses.fi/problemset/task/1633 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +#include + +using namespace std; + +const int mod = 1e9 + 7; +int dp[1000005]; + +int dice(int n) { + int resp = 0; + + // caso base + if (n == 0) return 1; + + // se ja calculamos a dp + if (dp[n] > 0) { + return dp[n]; + } + for (int i = 1; i<= 6; i++) { + if (n - i >= 0) { + resp += dice(n-i); + + // lembrar de tirar o modulo + resp %= mod; + } + } + return dp[n] = resp; +} + +int main () { + int n; + cin >> n; + cout << dice(n) << endl; + return 0; +} \ No newline at end of file diff --git a/cses/dp/10 - Edit Distance.cpp b/cses/dp/10 - Edit Distance.cpp new file mode 100644 index 0000000..2f625d1 --- /dev/null +++ b/cses/dp/10 - Edit Distance.cpp @@ -0,0 +1,43 @@ +// Edit Distance +// +// Problem name: Edit Distance +// Problem Link: https://cses.fi/problemset/task/1639 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +// The edit distance between two strings is the minimum number of operations required to transform one string into the other. +// The allowed operations are: +// Add one character to the string. +// Remove one character from the string. +// Replace one character in the string. +// For example, the edit distance between LOVE and MOVIE is 2, because you can first replace L with M, and then add I. +// Your task is to calculate the edit distance between two strings. + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 1000100 +#define INF 100000000 +#define pb push_back +#define F first +#define S second + +using namespace std; +typedef long long int ll; +typedef pair pii; +const int M = 1e9+7; + +int main () { _ + string a, b; + cin >> a >> b; + int tama = (int)a.size(), tamb = (int)b.size(); + vector> dp(5050, vector (5050, 10000)); + dp[tama][tamb] = 0; + for (int i = tama; i >= 0; i--) { + for (int j = tamb; j >= 0; j--) { + dp[i][j] = min(dp[i][j], (a[i] != b[j]) + dp[i+1][j+1]); + dp[i][j] = min(dp[i][j], 1 + dp[i+1][j]); + dp[i][j] = min(dp[i][j], 1 + dp[i][j+1]); + } + } + cout << dp[0][0] << '\n'; + return 0; +} \ No newline at end of file diff --git a/cses/dp/11 - Rectangle Cutting.cpp b/cses/dp/11 - Rectangle Cutting.cpp new file mode 100644 index 0000000..5be643f --- /dev/null +++ b/cses/dp/11 - Rectangle Cutting.cpp @@ -0,0 +1,41 @@ +// Rectangle Cutting +// +// Problem name: Rectangle Cutting +// Problem Link: https://cses.fi/problemset/task/1744 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +// Given an a×b rectangle, your task is to cut it into squares. +// On each move you can select a rectangle and cut it into two rectangles +// in such a way that all side lengths remain integers. What is the minimum possible number of moves? + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 1000100 +#define INF 100000000 +#define pb push_back +#define F first +#define S second + +using namespace std; +typedef long long int ll; +typedef pair pii; +const int M = 1e9+7; + +int main () { _ + int a, b; + cin >> a >> b; + vector> dp(505, vector (505, INF)); + for (int i = 1; i <= a; i++) { + dp[i][i] = 0; + for (int j = 1; j <= b; j++) { + for (int k = 1; k < j; k++) { + dp[i][j] = min(dp[i][j], 1 + dp[i][j-k] + dp[i][k]); + } + for (int k = 1; k < i; k++) { + dp[i][j] = min(dp[i][j], 1 + dp[i-k][j] + dp[k][j]); + } + } + } + cout << dp[a][b] << '\n'; + return 0; +} \ No newline at end of file diff --git a/cses/dp/12 - Money Sums.cpp b/cses/dp/12 - Money Sums.cpp new file mode 100644 index 0000000..c82f0ca --- /dev/null +++ b/cses/dp/12 - Money Sums.cpp @@ -0,0 +1,41 @@ +// Money Sums +// +// Problem name: Money Sums +// Problem Link: https://cses.fi/problemset/task/1745 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 1000100 +#define INF 100000000 +#define pb push_back +#define F first +#define S second + +using namespace std; +typedef long long int ll; +typedef pair pii; +const int M = 1e9+7; + +int main () { _ + int n; + cin >> n; + vector v(n); + for (int i = 0; i < n; i++) cin >> v[i]; + vector dp(1e5 + 5); + dp[0] = 1; + int c = 0; + for (int i = 0; i < n; i++) { + for (int j = 1e5; j >= 0; j--) { + if (dp[j] && j+v[i] <= 1e5) { + c += (dp[j+v[i]] == 0); + dp[j+v[i]] = 1; + } + } + } + cout << c << '\n'; + for (int i = 1; i <= 1e5; i++) + if (dp[i]) cout << i << ' '; + cout << '\n'; + return 0; +} \ No newline at end of file diff --git a/cses/dp/13 - Removal game.cpp b/cses/dp/13 - Removal game.cpp new file mode 100644 index 0000000..bf38fec --- /dev/null +++ b/cses/dp/13 - Removal game.cpp @@ -0,0 +1,40 @@ +// Removal Game +// +// Problem name: Removal Game +// Problem Link: https://cses.fi/problemset/task/1097 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 1000100 +#define INF 100000000 +#define pb push_back +#define F first +#define S second + +using namespace std; +typedef long long int ll; +typedef pair pii; +const int M = 1e9+7; + +int main () { _ + int n; + cin >> n; + vector v(n); + vector> dp(n, vector (n)); + ll soma = 0; + for (int i = 0; i < n; i++) { + cin >> v[i]; + soma += v[i]; + dp[i][i] = v[i]; + } + for (int j = 1; j < n; j++) { + for (int i = 0; i < n; i++) { + if (i + j < n) { + dp[i][i+j] = max(v[i] - dp[i+1][i+j], v[i+j] - dp[i][i+j-1]); + } + } + } + cout << (soma+dp[0][n-1])/2 << '\n'; + return 0; +} \ No newline at end of file diff --git a/cses/dp/14 - Two Sets II.cpp b/cses/dp/14 - Two Sets II.cpp new file mode 100644 index 0000000..1d32edd --- /dev/null +++ b/cses/dp/14 - Two Sets II.cpp @@ -0,0 +1,49 @@ +// Two Sets II +// +// Problem name: Two Sets II +// Problem Link: https://cses.fi/problemset/task/1093 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 1000100 +#define INF 100000000 +#define pb push_back +#define F first +#define S second + +using namespace std; +typedef long long int ll; +typedef pair pii; +const int M = 1e9+7; + +int fexp(ll b, int e) { + ll resp = 1; + while (e) { + if (e&1) resp = (resp * b) % M; + b = (b * b) % M; + e = (e >> 1); + } + return resp; +} + +int main () { _ + int n; + cin >> n; + if ((n%4) && ((n+1)%4)) cout << "0\n"; + else { + int meta = n*(n+1)/4; + vector dp(meta+1); + dp[0] = 1; + for (int i = 1; i <= n; i++) { + for (int j = meta; j >= 0; j--) { + if (j+i <= meta) { + dp[j+i] += dp[j]; + if (dp[j+i] >= M) dp[j+i] -= M; + } + } + } + cout << (dp[meta] * fexp(2, M-2)) % M << '\n'; + } + return 0; +} \ No newline at end of file diff --git a/cses/dp/15 - Projects.cpp b/cses/dp/15 - Projects.cpp new file mode 100644 index 0000000..843eb25 --- /dev/null +++ b/cses/dp/15 - Projects.cpp @@ -0,0 +1,52 @@ +// Projects +// +// Problem name: Projects +// Problem Link: https://cses.fi/problemset/task/1140 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 1000100 +#define INF 100000000 +#define pb push_back +#define F first +#define S second + +using namespace std; +typedef long long int ll; +typedef pair pii; +const int M = 1e9+7; + +int main () { _ + int n; + cin >> n; + vector> v(n); + vector c; + for (int i = 0; i < n; i++) { + cin >> v[i].F.F >> v[i].F.S >> v[i].S; + c.pb(v[i].F.F), c.pb(v[i].F.S); + } + sort(c.begin(), c.end()); + map mapa; + int atual = 0; + mapa[c[0]] = atual++; + for (int i = 1; i < (int)c.size(); i++) { + if (c[i] != c[i-1]) mapa[c[i]] = atual++; + } + for (int i = 0; i < n; i++) { + v[i].F.F = mapa[v[i].F.F]; + v[i].F.S = mapa[v[i].F.S]; + } + sort(v.begin(), v.end()); + vector dp(1e6); + atual = n-1; + for (int i = 5e5; i >= 0; i--) { + dp[i] = max(dp[i], dp[i+1]); + while (atual >= 0 && i == v[atual].F.F) { + dp[i] = max(dp[i], v[atual].S + dp[v[atual].F.S + 1]); + atual--; + } + } + cout << dp[0] << '\n'; + return 0; +} \ No newline at end of file diff --git a/cses/dp/16 - Increasing Subsequence.cpp b/cses/dp/16 - Increasing Subsequence.cpp new file mode 100644 index 0000000..0234d5d --- /dev/null +++ b/cses/dp/16 - Increasing Subsequence.cpp @@ -0,0 +1,40 @@ +// Increasing Subsequence +// +// Problem name: Increasing Subsequence +// Problem Link: https://cses.fi/problemset/task/1145 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +// You are given an array containing n integers. Your task is to determine the longest +//increasing subsequence in the array, i.e., +// the longest subsequence where every element is larger than the previous one. +// A subsequence is a sequence that can be derived from the array by deleting +// some elements without changing the order of the remaining elements. + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 1000100 +#define INF 100000000 +#define pb push_back +#define F first +#define S second + +using namespace std; +typedef long long int ll; +typedef pair pii; +const int M = 1e9+7; + +int main () { _ + int n; + cin >> n; + vector v(n), pilha; + for (int i = 0; i < n; i++) { + cin >> v[i]; + auto it = lower_bound(pilha.begin(), pilha.end(), v[i]); + if (it == pilha.end()) { + pilha.pb(v[i]); + } + else *it = v[i]; + } + cout << (int)pilha.size() << '\n'; + return 0; +} \ No newline at end of file diff --git a/cses/dp/17 - Elevator Rides.cpp b/cses/dp/17 - Elevator Rides.cpp new file mode 100644 index 0000000..ff7d51e --- /dev/null +++ b/cses/dp/17 - Elevator Rides.cpp @@ -0,0 +1,46 @@ +// Elevator Rides +// +// Problem name: Elevator Rides +// Problem Link: https://cses.fi/problemset/task/1653 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +// There are n people who want to get to the top of a building which has only one elevator. +// You know the weight of each person and the maximum allowed weight in the elevator. +// What is the minimum number of elevator rides? + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 1000100 +#define INF 100000000 +#define pb push_back +#define F first +#define S second + +using namespace std; +typedef long long int ll; +typedef pair pii; +const int M = 1e9+7; + +int main () { _ + int n, x; + cin >> n >> x; + vector v(n); + for (int i = 0; i < n; i++) cin >> v[i]; + vector dp((1<<21), {n+1, 0}); + dp[0] = {0, 0}; + for (int i = 1; i < (1 << n); i++) { + for (int j = 0; j < n; j++) { + if (i & (1< x) { + next.F++; + next.S = v[j]; + } + else next.S += v[j]; + dp[i] = min(dp[i], next); + } + } + } + cout << dp[(1<= 0) << '\n'; + return 0; +} \ No newline at end of file diff --git a/cses/dp/18 - Counting Tilings.cpp b/cses/dp/18 - Counting Tilings.cpp new file mode 100644 index 0000000..685b309 --- /dev/null +++ b/cses/dp/18 - Counting Tilings.cpp @@ -0,0 +1,61 @@ +// Counting Tilings +// +// Problem name: Counting Tilings +// Problem Link: https://cses.fi/problemset/task/2181 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +// Your task is to count the number of ways you can fill an n×m grid using 1×2 and 2×1 tiles + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 1000100 +#define INF 100000000 +#define pb push_back +#define F first +#define S second + +using namespace std; +typedef long long int ll; +typedef pair pii; +const int M = 1e9+7; + +int main () { _ + int n, m; + cin >> n >> m; + vector> v((1<> dp(1010, vector (1<<(n+1))); + for (int i = 0; i < (1<= M) dp[i][j] -= M; + } + } + } + cout << dp[m][0] << '\n'; + return 0; +} \ No newline at end of file diff --git a/cses/dp/19 - Counting Numbers.cpp b/cses/dp/19 - Counting Numbers.cpp new file mode 100644 index 0000000..b41ead3 --- /dev/null +++ b/cses/dp/19 - Counting Numbers.cpp @@ -0,0 +1,66 @@ +// Counting Numbers +// +// Problem name: Counting Numbers +// Problem Link: https://cses.fi/problemset/task/2220 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +// Your task is to count the number of integers between a and b where no two adjacent digits are the same. + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 1000100 +#define INF 100000000 +#define pb push_back +#define F first +#define S second + +using namespace std; +typedef long long int ll; +typedef pair pii; +const int M = 1e9+7; + +char cnum[10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}; +string a, b; +ll dp[20][11][2][2][2]; +// pos na string, ultimo digito, flag de ultrapassar, flag pra qual string estamos vendo, flag pra se ja teve num > 0 + +ll count(int pos, int ult, bool flag, bool pri, bool ja) { + ll &resp = dp[pos][ult][flag][pri][ja]; + if (resp >= 0) return resp; + if ((pri ? pos == (int)a.size() : pos == (int)b.size())) return 1ll; + ll ans = 0; + if (pri) { + for (int i = 0; i < 10; i++) { + if (cnum[i] > a[pos] && flag) break; + if (cnum[i] == a[pos] && i != ult) { + ans += count(pos+1, (!i && !ja ? 10 : i), flag, pri, (!i ? ja : true)); + } + else if ((cnum[i] < a[pos] || !flag) && i != ult) { + ans += count(pos+1, (!i && !ja ? 10 : i), false, pri, (!i ? ja : true)); + } + } + } + else { + for (int i = 0; i < 10; i++) { + if (cnum[i] > b[pos] && flag) break; + if (cnum[i] == b[pos] && i != ult) { + ans += count(pos+1, (!i && !ja ? 10 : i), flag, pri, (!i ? ja : true)); + } + else if ((cnum[i] < b[pos] || !flag) && i != ult) { + ans += count(pos+1, (!i && !ja ? 10 : i), false, pri, (!i ? ja : true)); + } + } + } + return resp = ans; +} + +int main () { _ + ll c; + memset(dp, -1, sizeof(dp)); + cin >> c >> b; + c--; + a = to_string(c); + ll ans = count(0, 10, true, false, false) - (c >= 0 ? count(0, 10, true, true, false) : 0ll); + cout << ans << '\n'; + return 0; +} \ No newline at end of file diff --git a/cses/dp/2 - Minimizing Coins.cpp b/cses/dp/2 - Minimizing Coins.cpp new file mode 100644 index 0000000..6186cb1 --- /dev/null +++ b/cses/dp/2 - Minimizing Coins.cpp @@ -0,0 +1,36 @@ +// Minimizing Coins +// +// Problem name: Minimizing Coins +// Problem Link: https://cses.fi/problemset/task/1634 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 1000100 +#define INF 1000005 + +using namespace std; +typedef long long int lli; + +int dp[MAXN], n, x, v[105]; + +int coin(int soma) { + if (dp[soma] > 0) return dp[soma]; + if (soma == 0) return 0; + int resp = INF; + for (int i = n; i > 0; i--) { + if (soma-v[i] >= 0) resp = min(resp, 1+coin(soma-v[i])); + } + return dp[soma] = resp; +} + +int main () { + cin >> n >> x; + for (int i = 1; i <= n; i++) { + cin >> v[i]; + } + int ans = coin(x); + if (ans > 1000000) cout << "-1" << endl; + else cout << ans << endl; + return 0; +} \ No newline at end of file diff --git a/cses/dp/3 - Coin Combinations I.cpp b/cses/dp/3 - Coin Combinations I.cpp new file mode 100644 index 0000000..b822f61 --- /dev/null +++ b/cses/dp/3 - Coin Combinations I.cpp @@ -0,0 +1,41 @@ +// Coin Combinations I +// +// Problem name: Coin Combinations I +// Problem Link: https://cses.fi/problemset/task/1635 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 1000100 +#define INF 1000005 + +using namespace std; +typedef long long int lli; + +const int mod = 1e9 + 7; +int dp[MAXN], n, x, v[105]; + +int coin(int soma) { + if (dp[soma] >= 0) return dp[soma]; + int resp = 0; + for (int i = 1; i <= n; i++) { + if (soma - v[i] >= 0) { + resp += coin(soma-v[i]); + resp %= mod; + } + else break; + } + return dp[soma] = resp; +} + +int main () { _ + memset(dp, -1, sizeof(dp)); + cin >> n >> x; + for (int i = 1; i <= n; i++) { + cin >> v[i]; + } + sort(v+1, v+n+1); + dp[0] = 1; + cout << coin(x) << endl; + return 0; +} \ No newline at end of file diff --git a/cses/dp/4 - Coin Combinations II.cpp b/cses/dp/4 - Coin Combinations II.cpp new file mode 100644 index 0000000..ae796eb --- /dev/null +++ b/cses/dp/4 - Coin Combinations II.cpp @@ -0,0 +1,38 @@ +// Coin Combinations II +// +// Problem name: Coin Combinations II +// Problem Link: https://cses.fi/problemset/task/1636 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 1000100 +#define INF 100000000 +#define pb push_back +#define F first +#define S second + +using namespace std; +typedef long long int ll; +typedef pair pii; +const int M = 1e9+7; + +int main () { _ + int n, x; + cin >> n >> x; + vector coin(n), dp(x+1); + for (int i = 0; i < n; i++) { + cin >> coin[i]; + } + sort(coin.begin(), coin.end()); + dp[0] = 1; + for (int i = 0; i < n; i++) { + int atual = coin[i]; + for (int j = atual; j <= x; j++) { + dp[j] = dp[j] + dp[j-atual]; + if (dp[j] >= M) dp[j] -= M; + } + } + cout << dp[x] << '\n'; + return 0; +} \ No newline at end of file diff --git a/cses/dp/5 - Removing Digits.cpp b/cses/dp/5 - Removing Digits.cpp new file mode 100644 index 0000000..a70f7ae --- /dev/null +++ b/cses/dp/5 - Removing Digits.cpp @@ -0,0 +1,33 @@ +// Removing Digits +// +// Problem name: Removing Digits +// Problem Link: https://cses.fi/problemset/task/1637 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 1000100 +#define INF 1000005 + +using namespace std; +typedef long long int lli; + +int dp[MAXN]; + +int digit(int x) { + if (x == 0) return 0; + if (dp[x] > 0) return dp[x]; + string s = to_string(x); + int resp = INF; + for (int i = 0; i < (int)s.size(); i++) { + if (s.at(i) != '0') resp = min(resp, 1 + digit(x-(int)s.at(i)+48)); + } + return dp[x] = resp; +} + +int main () { _ + int n; + cin >> n; + cout << digit(n) << endl; + return 0; +} \ No newline at end of file diff --git a/cses/dp/6 - Grid Paths.cpp b/cses/dp/6 - Grid Paths.cpp new file mode 100644 index 0000000..08f91a7 --- /dev/null +++ b/cses/dp/6 - Grid Paths.cpp @@ -0,0 +1,48 @@ +// Grid Paths +// +// Problem name: Grid Paths +// Problem Link: https://cses.fi/problemset/task/1638 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 1000100 +#define INF 1000005 + +using namespace std; +typedef long long int lli; +const int mod = 1e9+7; + +int dp[1010][1010], n; +bool m[1010][1010]; + +int ways (int i, int j) { + if (dp[i][j] >= 0) return dp[i][j]; + int resp = 0; + if (i < n and m[i+1][j]) { + resp += ways(i+1, j); + resp %= mod; + } + if (j < n and m[i][j+1]) { + resp += ways(i, j+1); + resp %= mod; + } + return dp[i][j] = resp; +} + +int main () { _ + char c; + memset(dp, -1, sizeof(dp)); + cin >> n; + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + cin >> c; + if (c == '.') m[i][j] = true; + else m[i][j] = false; + } + } + dp[n-1][n-1] = 1; + if (!m[0][0]) cout << "0" << endl; + else cout << ways(0,0) << endl; + return 0; +} \ No newline at end of file diff --git a/cses/dp/7 - Book Shop.cpp b/cses/dp/7 - Book Shop.cpp new file mode 100644 index 0000000..a98d9fd --- /dev/null +++ b/cses/dp/7 - Book Shop.cpp @@ -0,0 +1,40 @@ +// Book Shop +// +// Problem name: Book Shop +// Problem Link: https://cses.fi/problemset/task/1158 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 1000100 +#define INF 100000000 +#define pb push_back +#define F first +#define S second + +using namespace std; +typedef long long int ll; +typedef pair pii; +const int M = 1e9+7; + +int main () { _ + int n, x; + cin >> n >> x; + vector h(n), v(n); + for (int i = 0; i < n; i++) cin >> h[i]; + for (int i = 0; i < n; i++) cin >> v[i]; + vector> dp(n+1, vector (x+1, -1)); + dp[0][x] = 0; + for (int i = 0; i < n; i++) { + for (int j = x; j >= 0; j--) { + if (dp[i][j] >= 0) { + dp[i+1][j] = max(dp[i+1][j], dp[i][j]); + if (j >= h[i]) dp[i+1][j-h[i]] = max(dp[i+1][j-h[i]], dp[i][j] + v[i]); + } + } + } + int ans = 0; + for (int i = x; i >= 0; i--) ans = max(ans, dp[n][i]); + cout << ans << '\n'; + return 0; +} \ No newline at end of file diff --git a/cses/dp/8 - Array Description.cpp b/cses/dp/8 - Array Description.cpp new file mode 100644 index 0000000..9bf34bd --- /dev/null +++ b/cses/dp/8 - Array Description.cpp @@ -0,0 +1,45 @@ +// Array Description +// +// Problem name: Array Description +// Problem Link: https://cses.fi/problemset/task/1746 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 1000100 +#define INF 100000000 +#define pb push_back +#define F first +#define S second + +using namespace std; +typedef long long int ll; +typedef pair pii; +const int M = 1e9+7; + +int main () { _ + int n, m; + cin >> n >> m; + vector v(n); + for (int i = 0; i < n; i++) cin >> v[i]; + vector> dp(n+1, vector (m+2, 0)); + for (int i = 1; i <= m; i++) { + if (!v[0] || v[0] == i) dp[0][i] = 1; + } + for (int i = 1; i < n; i++) { + for (int j = 1; j <= m; j++) { + if (!v[i] || v[i] == j) { + dp[i][j] = (dp[i-1][j-1] + dp[i-1][j] + dp[i-1][j+1]) % M; + } + } + } + int ans = 0; + for (int i = 1; i <= m; i++) { + if (v[n-1] == i || !v[n-1]) { + ans += dp[n-1][i]; + if (ans >= M) ans -= M; + } + } + cout << ans << '\n'; + return 0; +} \ No newline at end of file diff --git a/cses/dp/9 - Counting Towers.cpp b/cses/dp/9 - Counting Towers.cpp new file mode 100644 index 0000000..9e117ff --- /dev/null +++ b/cses/dp/9 - Counting Towers.cpp @@ -0,0 +1,38 @@ +// Counting Towers +// +// Problem name: Counting Towers +// Problem Link: https://cses.fi/problemset/task/2413 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 1000100 +#define INF 100000000 +#define pb push_back +#define F first +#define S second + +using namespace std; +typedef long long int ll; +typedef pair pii; +const int M = 1e9+7; + +int main () { _ + int t; + cin >> t; + vector> dp(1e6+5, vector (5)); + dp[1][0] = 2, dp[1][1] = dp[1][2] = dp[1][3] = dp[1][4] = 1; + for (int i = 1; i <= 1e6; i++) { + dp[i+1][0] = (2*dp[i][0] + dp[i][1] + dp[i][2] + dp[i][3] + dp[i][4]) % M; + dp[i+1][1] = (dp[i][0] + dp[i][1] + dp[i][2] + dp[i][3]) % M; + dp[i+1][2] = dp[i+1][1]; + dp[i+1][3] = (dp[i][0] + dp[i][1] + dp[i][2] + dp[i][3]) % M; + dp[i+1][4] = (dp[i][0] + dp[i][4]) % M; + } + while (t--) { + int n; + cin >> n; + cout << dp[n][0] << '\n'; + } + return 0; +} \ No newline at end of file From 44737f046fb6648716c077d527d7b4a117bb870c Mon Sep 17 00:00:00 2001 From: Bernardo Panka Archegas Date: Fri, 8 Nov 2024 15:07:58 -0300 Subject: [PATCH 2/2] Added graph section --- cses/README.md | 6 + cses/graph/1 - Counting Rooms.cpp | 47 ++++++ cses/graph/10 - High Score.cpp | 69 +++++++++ cses/graph/11 - Flight Discount.cpp | 84 ++++++++++ cses/graph/12 - Cycle Finding.cpp | 65 ++++++++ cses/graph/13 - Flight Routes.cpp | 70 +++++++++ cses/graph/14 - Round Trip II.cpp | 69 +++++++++ cses/graph/15 - Course Schedule.cpp | 60 ++++++++ cses/graph/16 - Longest Flight Route.cpp | 56 +++++++ cses/graph/17 - Game Routes.cpp | 44 ++++++ cses/graph/18 - Investigation.cpp | 94 ++++++++++++ cses/graph/19 - Planets Queries I.cpp | 44 ++++++ cses/graph/2 - Labyrinth.cpp | 78 ++++++++++ cses/graph/20 - Planets Queries II.cpp | 108 +++++++++++++ cses/graph/21 - Planets Cycles.cpp | 62 ++++++++ cses/graph/22 - Road Reparation.cpp | 67 ++++++++ cses/graph/23 - Road Construction.cpp | 64 ++++++++ cses/graph/24 - Flight Routes Check.cpp | 67 ++++++++ cses/graph/25 - Planets and Kingdoms.cpp | 67 ++++++++ cses/graph/26 - Giant Pizza.cpp | 99 ++++++++++++ cses/graph/27 - Coin Collector.cpp | 82 ++++++++++ cses/graph/28 - Mail Delivery.cpp | 80 ++++++++++ cses/graph/29 - De Bruijn Sequence.cpp | 61 ++++++++ cses/graph/3 - Building Roads.cpp | 63 ++++++++ cses/graph/30 - Teleporters Path.cpp | 74 +++++++++ cses/graph/31 - Hamiltonian Flights.cpp | 49 ++++++ cses/graph/32 - Knight's Tour.cpp | 68 +++++++++ cses/graph/33 - Download Speed.cpp | 187 +++++++++++++++++++++++ cses/graph/34 - Police Chase.cpp | 128 ++++++++++++++++ cses/graph/35 - School Dance.cpp | 135 ++++++++++++++++ cses/graph/36 - Distinct Routes.cpp | 152 ++++++++++++++++++ cses/graph/4 - Message Route.cpp | 70 +++++++++ cses/graph/5 - Building Teams.cpp | 56 +++++++ cses/graph/6 - Round Trip.cpp | 73 +++++++++ cses/graph/7 - Monsters.cpp | 127 +++++++++++++++ cses/graph/8 - Shortest Routes I.cpp | 57 +++++++ cses/graph/9 - Shortest Routes II.cpp | 54 +++++++ 37 files changed, 2836 insertions(+) create mode 100644 cses/README.md create mode 100644 cses/graph/1 - Counting Rooms.cpp create mode 100644 cses/graph/10 - High Score.cpp create mode 100644 cses/graph/11 - Flight Discount.cpp create mode 100644 cses/graph/12 - Cycle Finding.cpp create mode 100644 cses/graph/13 - Flight Routes.cpp create mode 100644 cses/graph/14 - Round Trip II.cpp create mode 100644 cses/graph/15 - Course Schedule.cpp create mode 100644 cses/graph/16 - Longest Flight Route.cpp create mode 100644 cses/graph/17 - Game Routes.cpp create mode 100644 cses/graph/18 - Investigation.cpp create mode 100644 cses/graph/19 - Planets Queries I.cpp create mode 100644 cses/graph/2 - Labyrinth.cpp create mode 100644 cses/graph/20 - Planets Queries II.cpp create mode 100644 cses/graph/21 - Planets Cycles.cpp create mode 100644 cses/graph/22 - Road Reparation.cpp create mode 100644 cses/graph/23 - Road Construction.cpp create mode 100644 cses/graph/24 - Flight Routes Check.cpp create mode 100644 cses/graph/25 - Planets and Kingdoms.cpp create mode 100644 cses/graph/26 - Giant Pizza.cpp create mode 100644 cses/graph/27 - Coin Collector.cpp create mode 100644 cses/graph/28 - Mail Delivery.cpp create mode 100644 cses/graph/29 - De Bruijn Sequence.cpp create mode 100644 cses/graph/3 - Building Roads.cpp create mode 100644 cses/graph/30 - Teleporters Path.cpp create mode 100644 cses/graph/31 - Hamiltonian Flights.cpp create mode 100644 cses/graph/32 - Knight's Tour.cpp create mode 100644 cses/graph/33 - Download Speed.cpp create mode 100644 cses/graph/34 - Police Chase.cpp create mode 100644 cses/graph/35 - School Dance.cpp create mode 100644 cses/graph/36 - Distinct Routes.cpp create mode 100644 cses/graph/4 - Message Route.cpp create mode 100644 cses/graph/5 - Building Teams.cpp create mode 100644 cses/graph/6 - Round Trip.cpp create mode 100644 cses/graph/7 - Monsters.cpp create mode 100644 cses/graph/8 - Shortest Routes I.cpp create mode 100644 cses/graph/9 - Shortest Routes II.cpp diff --git a/cses/README.md b/cses/README.md new file mode 100644 index 0000000..6389fdc --- /dev/null +++ b/cses/README.md @@ -0,0 +1,6 @@ +CSES is one of the most complete problemsets on the internet, with over 300 problems of all topics. +https://cses.fi/problemset/list/ + +In here we have all solutions to the problems of the dp and graph sections + +All the problems can be tested on the cses website, where you can also access the test cases, and once you solved the problem, access other solutions \ No newline at end of file diff --git a/cses/graph/1 - Counting Rooms.cpp b/cses/graph/1 - Counting Rooms.cpp new file mode 100644 index 0000000..c76d628 --- /dev/null +++ b/cses/graph/1 - Counting Rooms.cpp @@ -0,0 +1,47 @@ +// Counting Rooms +// +// Problem name: Counting Rooms +// Problem Link: https://cses.fi/problemset/task/1192 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 200100 +#define INF 10000000000 + +using namespace std; +typedef long long int lli; +const int mod = 1e9+7; + +int n, m, matriz[1010][1010], resp = 0; +bool check[1010][1010]; + +void DFS (int i, int j) { + check[i][j] = true; + if (i+1 < n and !check[i+1][j] and !matriz[i+1][j]) DFS(i+1, j); + if (i-1 >= 0 and !check[i-1][j] and !matriz[i-1][j]) DFS(i-1, j); + if (j+1 < m and !check[i][j+1] and !matriz[i][j+1]) DFS(i, j+1); + if (j-1 >= 0 and !check[i][j-1] and !matriz[i][j-1]) DFS(i, j-1); +} + +int main() { _ + char c; + cin >> n >> m; + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + cin >> c; + if (c == '.') matriz[i][j] = 0; + else matriz[i][j] = 1; + } + } + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + if (!check[i][j] and !matriz[i][j]) { + DFS(i, j); + resp++; + } + } + } + cout << resp << endl; + return 0; +} \ No newline at end of file diff --git a/cses/graph/10 - High Score.cpp b/cses/graph/10 - High Score.cpp new file mode 100644 index 0000000..c63f510 --- /dev/null +++ b/cses/graph/10 - High Score.cpp @@ -0,0 +1,69 @@ +// High Score +// +// Problem name: High Score +// Problem Link: https://cses.fi/problemset/task/1673 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 5050 +#define INF 1e17 +#define pb push_back +#define F first +#define S second + +using namespace std; +typedef long long int ll; +typedef pair pii; +typedef pair pll; +mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); +const int M = 998244353; + +vector> v; +vector u[MAXN], w[MAXN]; +ll dist[MAXN]; +int inv[MAXN], vis1[MAXN], vis2[MAXN]; + +void dfs1(int node) { + vis1[node] = 1; + for (int x : u[node]) + if (!vis1[x]) dfs1(x); +} + +void dfs2(int node) { + vis2[node] = 1; + for (int x : w[node]) + if (!vis2[x]) dfs2(x); +} + +int main() { _ + int n, m; + cin >> n >> m; + array a; + for (int i = 0; i < m; i++) { + cin >> a[0] >> a[1] >> a[2]; + a[2] = -a[2]; + v.pb(a); + u[a[0]].pb(a[1]); + w[a[1]].pb(a[0]); + } + for (int i = 2; i <= n; i++) dist[i] = INF; + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + dist[v[j][1]] = min(dist[v[j][1]], dist[v[j][0]] + v[j][2]); + } + } + for (int j = 0; j < m; j++) { + if (dist[v[j][0]] + v[j][2] < dist[v[j][1]]) inv[v[j][1]] = 1; + } + bool ok = true; + dfs1(1); + dfs2(n); + ll ans = -dist[n]; + for (int i = 1; i <= n; i++) { + if (inv[i] && vis1[i] && vis2[i]) ok = 0; + } + if (!ok) ans = -1; + cout << ans << '\n'; + return 0; +} \ No newline at end of file diff --git a/cses/graph/11 - Flight Discount.cpp b/cses/graph/11 - Flight Discount.cpp new file mode 100644 index 0000000..f165fd8 --- /dev/null +++ b/cses/graph/11 - Flight Discount.cpp @@ -0,0 +1,84 @@ +// Flight Discount +// +// Problem name: Flight Discount +// Problem Link: https://cses.fi/problemset/task/1195 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 200100 +#define INF 1e17 +#define pb push_back +#define F first +#define S second + +using namespace std; +typedef long long int ll; +typedef pair pii; +const int M = 1e9+7; + +vector v[MAXN]; +ll dist[MAXN][10], n, m, coupons = 1; + +struct d { + int no; + int sale; + ll di; + + d(int _no = 0, ll _di = 0, int _sale = 0) { + no = _no; + di = _di; + sale = _sale; + } + + inline const bool operator<(const d& other) const { + if (sale == other.sale) { + return di > other.di; + } + return sale > other.sale; + } +}; + +void dijkstra(int node) { + for (int i = 1; i <= n; i++) { + for (int j = 0; j < 10; j++) dist[i][j] = INF; + } + dist[node][0] = 0; + d aux; + aux.no = node, aux.di = 0, aux.sale = 0; + priority_queue fila; + fila.push(aux); + while (!fila.empty()) { + aux = fila.top(); + fila.pop(); + if (dist[aux.no][aux.sale] < aux.di) continue; + for (pii x : v[aux.no]) { + if (dist[x.F][aux.sale] > aux.di + x.S) { + dist[x.F][aux.sale] = aux.di + x.S; + d next; + next.no = x.F, next.di = dist[x.F][aux.sale], next.sale = aux.sale; + fila.push(next); + } + if (aux.sale < coupons) { + if (dist[x.F][aux.sale+1] > aux.di + x.S/2) { + dist[x.F][aux.sale+1] = aux.di + x.S/2; + d next; + next.no = x.F, next.di = dist[x.F][aux.sale+1], next.sale = aux.sale+1; + fila.push(next); + } + } + } + } +} + +int main () { _ + cin >> n >> m; + for (int i = 0; i < m; i++) { + int a, b, c; + cin >> a >> b >> c; + v[a].pb({b, c}); + } + dijkstra(1); + cout << dist[n][coupons] << '\n'; + return 0; +} \ No newline at end of file diff --git a/cses/graph/12 - Cycle Finding.cpp b/cses/graph/12 - Cycle Finding.cpp new file mode 100644 index 0000000..3f0ee0f --- /dev/null +++ b/cses/graph/12 - Cycle Finding.cpp @@ -0,0 +1,65 @@ +// Cycle Finding +// +// Problem name: Cycle Finding +// Problem Link: https://cses.fi/problemset/task/1197 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +// You are given a directed graph, and your task is to find out +// if it contains a negative cycle, and also give an example of such a cycle. + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 2550 +#define INF 1e17 +#define pb push_back +#define F first +#define S second + +using namespace std; +typedef long long int ll; +typedef pair pii; +typedef pair pll; +mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); +const int M = 998244353; + +vector> v; +ll dist[MAXN]; +int p[MAXN]; + +int main() { _ + int n, m; + cin >> n >> m; + array a; + for (int i = 0; i < m; i++) { + cin >> a[0] >> a[1] >> a[2]; + v.pb(a); + } + int x = -1; + for (int i = 2; i <= n; i++) dist[i] = INF; + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + if (dist[v[j][0]] + v[j][2] < dist[v[j][1]]) { + dist[v[j][1]] = dist[v[j][0]] + v[j][2]; + p[v[j][1]] = v[j][0]; + if (i == n-1) x = v[j][1]; + } + } + } + if (x == -1) cout << "NO\n"; + else { + cout << "YES\n"; + for (int i = 0; i < n; i++) x = p[x]; + stack ans; + ans.push(x); + for (int i = p[x]; i != x; i = p[i]) { + ans.push(i); + } + ans.push(x); + while (!ans.empty()) { + cout << ans.top() << ' '; + ans.pop(); + } + cout << '\n'; + } + return 0; +} \ No newline at end of file diff --git a/cses/graph/13 - Flight Routes.cpp b/cses/graph/13 - Flight Routes.cpp new file mode 100644 index 0000000..d515193 --- /dev/null +++ b/cses/graph/13 - Flight Routes.cpp @@ -0,0 +1,70 @@ +// Flight Routes +// +// Problem name: Flight Routes +// Problem Link: https://cses.fi/problemset/task/1196 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +// Your task is to find the k shortest flight routes from Syrjälä to Metsälä. +// A route can visit the same city several times. +// Note that there can be several routes with the same price +// and each of them should be considered (see the example). + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 100100 +#define INF 1e17 +#define pb push_back +#define F first +#define S second + +using namespace std; +typedef long long int ll; +typedef pair pii; +typedef pair pll; +mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); +const int M = 998244353; + +vector v[MAXN]; +priority_queue dist[MAXN]; +int n, m, k; + +void dijkstra() { + for (int i = 1; i <= n; i++) { + for (int j = 0; j < k; j++) dist[i].push(INF); + } + dist[1].pop(); + dist[1].push(0); + priority_queue, greater> fila; + fila.push({0, 1}); + while (!fila.empty()) { + pll atual = fila.top(); + fila.pop(); + if (atual.F > dist[atual.S].top()) continue; + for (pii x : v[atual.S]) { + if (dist[x.F].top() > atual.F + x.S) { + dist[x.F].pop(); + dist[x.F].push(atual.F + x.S); + fila.push({atual.F + x.S, x.F}); + } + } + } +} + +int main() { _ + cin >> n >> m >> k; + for (int i = 0; i < m; i++) { + int a, b, c; + cin >> a >> b >> c; + v[a].pb({b, c}); + } + dijkstra(); + vector ans; + while (!dist[n].empty()) { + ans.pb(dist[n].top()); + dist[n].pop(); + } + reverse(ans.begin(), ans.end()); + for (ll x : ans) cout << x << ' '; + cout << '\n'; + return 0; +} \ No newline at end of file diff --git a/cses/graph/14 - Round Trip II.cpp b/cses/graph/14 - Round Trip II.cpp new file mode 100644 index 0000000..279b873 --- /dev/null +++ b/cses/graph/14 - Round Trip II.cpp @@ -0,0 +1,69 @@ +// Round Trip II +// +// Problem name: Round Trip II +// Problem Link: https://cses.fi/problemset/task/1678 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 200100 +#define INF 1000000001 +#define pb push_back +#define F first +#define S second + +using namespace std; +typedef long long int ll; +typedef pair pii; +const int M = 1e9+7; + +vector v[MAXN]; +stack ans; +int valid; +int cor[MAXN], go[MAXN]; + +void dfs(int node) { + cor[node] = 1; + for (int x : v[node]) { + if (cor[x] == 1 && ans.empty()) { + int ini = x; + valid = node; + ans.push(x); + while (valid != ini) { + ans.push(valid); + valid = go[valid]; + } + ans.push(valid); + } + if (!cor[x]) { + go[x] = node; + dfs(x); + } + } + cor[node] = 2; +} + +int main () { _ + int n, m; + cin >> n >> m; + for (int i = 0; i < m; i++) { + int a, b; + cin >> a >> b; + v[a].pb(b); + } + for (int i = 1; i <= n && !valid; i++) { + if (!cor[i]) { + dfs(i); + } + } + if (!valid) cout << "IMPOSSIBLE\n"; + else { + cout << ans.size() << '\n'; + while (!ans.empty()) { + cout << ans.top() << ' '; + ans.pop(); + } + cout << '\n'; + } + return 0; +} \ No newline at end of file diff --git a/cses/graph/15 - Course Schedule.cpp b/cses/graph/15 - Course Schedule.cpp new file mode 100644 index 0000000..057d147 --- /dev/null +++ b/cses/graph/15 - Course Schedule.cpp @@ -0,0 +1,60 @@ +// Course Schedule +// +// Problem name: Course Schedule +// Problem Link: https://cses.fi/problemset/task/1679 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +// You have to complete n courses. There are m requirements of the form "course a has to be completed before course b". +// Your task is to find an order in which you can complete the courses. + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 200100 +#define INF 1000000001 +#define pb push_back +#define F first +#define S second + +using namespace std; +typedef long long int ll; +typedef pair pii; +const int M = 1e9+7; + +vector v[MAXN], ans; +bool valid = true; +int cor[MAXN]; + +void dfs(int node) { + cor[node] = 1; + for (int x : v[node]) { + if (cor[x] == 1) { + valid = false; + return; + } + if (!cor[x]) dfs(x); + } + cor[node] = 2; + ans.pb(node); +} + +int main () { _ + int n, m; + cin >> n >> m; + for (int i = 0; i < m; i++) { + int a, b; + cin >> a >> b; + v[a].pb(b); + } + for (int i = 1; i <= n && valid; i++) { + if (!cor[i]) { + dfs(i); + } + } + if (!valid) cout << "IMPOSSIBLE\n"; + else { + reverse(ans.begin(), ans.end()); + for (int x : ans) cout << x << ' '; + cout << '\n'; + } + return 0; +} \ No newline at end of file diff --git a/cses/graph/16 - Longest Flight Route.cpp b/cses/graph/16 - Longest Flight Route.cpp new file mode 100644 index 0000000..2bf942f --- /dev/null +++ b/cses/graph/16 - Longest Flight Route.cpp @@ -0,0 +1,56 @@ +// Longest Flight Route +// +// Problem name: Longest Flight Route +// Problem Link: https://cses.fi/problemset/task/1680 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 100100 +#define INF 100000000 +#define pb push_back +#define F first +#define S second + +using namespace std; +typedef long long int ll; +typedef pair pii; +const int M = 1e9+7; + +int dp[MAXN], check[MAXN], go[MAXN], n; +vector v[MAXN]; + +void dfs(int node) { + dp[node] = (node == n ? 0 : -1e6); + for (int x : v[node]) { + if (!check[x]) dfs(x); + check[x] = 1; + if (dp[x] >= dp[node]) { + dp[node] = 1 + dp[x]; + go[node] = x; + } + } +} + +int main () { _ + int m; + cin >> n >> m; + for (int i = 0; i < m; i++) { + int a, b; + cin >> a >> b; + v[a].pb(b); + } + dfs(1); + if (dp[1] < 0) cout << "IMPOSSIBLE\n"; + else { + cout << dp[1] + 1 << '\n'; + cout << "1 "; + int atual = go[1]; + while (atual != 0) { + cout << atual << ' '; + atual = go[atual]; + } + cout << '\n'; + } + return 0; +} \ No newline at end of file diff --git a/cses/graph/17 - Game Routes.cpp b/cses/graph/17 - Game Routes.cpp new file mode 100644 index 0000000..8ba5646 --- /dev/null +++ b/cses/graph/17 - Game Routes.cpp @@ -0,0 +1,44 @@ +// Game Routes +// +// Problem name: Game Routes +// Problem Link: https://cses.fi/problemset/task/1681 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 1000100 +#define INF 100000000 +#define pb push_back +#define F first +#define S second + +using namespace std; +typedef long long int ll; +typedef pair pii; +const int M = 1e9+7; + +int dp[MAXN], check[MAXN]; +vector v[MAXN]; + +void dfs(int node) { + for (int x : v[node]) { + if (!check[x]) dfs(x); + check[x] = 1; + dp[node] += dp[x]; + if (dp[node] >= M) dp[node] -= M; + } +} + +int main () { _ + int n, m; + cin >> n >> m; + for (int i = 0; i < m; i++) { + int a, b; + cin >> a >> b; + v[a].pb(b); + } + dp[n] = 1; + dfs(1); + cout << dp[1] << '\n'; + return 0; +} \ No newline at end of file diff --git a/cses/graph/18 - Investigation.cpp b/cses/graph/18 - Investigation.cpp new file mode 100644 index 0000000..c092c12 --- /dev/null +++ b/cses/graph/18 - Investigation.cpp @@ -0,0 +1,94 @@ +// Investigation +// +// Problem name: Investigation +// Problem Link: https://cses.fi/problemset/task/1202 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +// You are going to travel from Syrjälä to Lehmälä by plane. You would like to find answers to the following questions: +// what is the minimum price of such a route? +// how many minimum-price routes are there? (modulo 109+7) +// what is the minimum number of flights in a minimum-price route? +// what is the maximum number of flights in a minimum-price route? + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 100100 +#define INF 1e17 +#define pb push_back +#define F first +#define S second + +using namespace std; +typedef long long int ll; +typedef pair pii; +typedef pair pll; +mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); +const int M = 1e9+7; + +vector v[MAXN], w[MAXN]; +ll dist[MAXN], quant[MAXN], mn[MAXN], mx[MAXN]; +int n, m, vis[MAXN]; + +void dijkstra(int node) { + for (int i = 1; i <= n; i++) dist[i] = INF; + dist[node] = 0; + priority_queue, greater> fila; + fila.push({0, node}); + while (!fila.empty()) { + pll atual = fila.top(); + fila.pop(); + if (dist[atual.S] < atual.F) continue; + for (pii x : v[atual.S]) { + if (dist[x.F] > atual.F + x.S) { + dist[x.F] = atual.F + x.S; + fila.push({dist[x.F], x.F}); + } + } + } +} + +void dag(int node) { + vis[node] = 1; + for (pii x : v[node]) { + if (dist[node] + x.S == dist[x.F]) { + w[node].pb(x); + if (!vis[x.F]) dag(x.F); + } + } +} + +void dfs(int node) { + vis[node] = 1; + for (pii x : w[node]) { + if (!vis[x.F]) dfs(x.F); + quant[node] += quant[x.F]; + if (quant[node] >= M) quant[node] -= M; + mn[node] = min(mn[node], mn[x.F]+1); + mx[node] = max(mx[node], mx[x.F]+1); + } +} + +int main () { _ + cin >> n >> m; + for (int i = 0; i < m; i++) { + int a, b, c; + cin >> a >> b >> c; + v[a].pb({b, c}); + } + dijkstra(1); + dag(1); + memset(vis, 0, sizeof(vis)); + for (int i = 1; i <= n; i++) { + mn[i] = INF; + mx[i] = -INF; + } + mn[n] = mx[n] = 0; + quant[n] = 1; + // min price = dist[n] + // how many routes + // min number of edges in route + // max number of edges in route + dfs(1); + cout << dist[n] << ' ' << quant[1] << ' ' << mn[1] << ' ' << mx[1] << '\n'; + return 0; +} \ No newline at end of file diff --git a/cses/graph/19 - Planets Queries I.cpp b/cses/graph/19 - Planets Queries I.cpp new file mode 100644 index 0000000..3a8bd9e --- /dev/null +++ b/cses/graph/19 - Planets Queries I.cpp @@ -0,0 +1,44 @@ +// Planets Queries I +// +// Problem name: Planets Queries I +// Problem Link: https://cses.fi/problemset/task/1750 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 1000100 +#define INF 1e17 +#define pb push_back +#define F first +#define S second + +using namespace std; +typedef long long int ll; +typedef pair pii; +mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); +const int M = 1e9+7; + +int tab[31][MAXN]; + +int main () { _ + int n, q; + cin >> n >> q; + for (int i = 1; i <= n; i++) { + cin >> tab[0][i]; + } + for (int i = 1; i < 31; i++) { + for (int j = 1; j <= n; j++) { + tab[i][j] = tab[i-1][tab[i-1][j]]; + } + } + for (int i = 0; i < q; i++) { + int a, b; + cin >> a >> b; + int atual = a; + for (int j = 0; j < 31; j++) { + if (b & (1< +using namespace std; +#define MAXN 1003 +#define MAXS 1003 +int n, m, inix, iniy, fimx, fimy; +int vis[MAXN][MAXS]; +char path[MAXN][MAXS]; +char mapa[MAXN][MAXS]; +int varx[] = {1, -1, 0, 0}; +int vary[] = {0, 0, 1, -1}; +int BFS(int a, int b) { + queue> q; + q.push({a, b}); + mapa[a][b] = '#'; + while(!q.empty()) { + int x = q.front().first; + int y = q.front().second; + q.pop(); + for (int i = 0; i < 4; i++) { + int X = varx[i] + x; + int Y = vary[i] + y; + if (X <= 0 || X > n || Y <= 0 || Y > m || mapa[X][Y] == '#') continue; + q.push({X, Y}); + vis[X][Y] = vis[x][y] + 1; + bool fim = (mapa[X][Y] == 'B'); + mapa[X][Y] = '#'; + if (i == 0) path[X][Y] = 'D'; + else if (i == 1) path[X][Y] = 'U'; + else if (i == 2) path[X][Y] = 'R'; + else path[X][Y] = 'L'; + if (fim) { + fimx = X; + fimy = Y; + return vis[X][Y]; + } + } + } + return 0; +} + +int main() { + memset(vis, 0, sizeof(vis)); + cin >> n >> m; + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= m; j++) { + cin >> mapa[i][j]; + if (mapa[i][j] == 'A') { + inix = i; + iniy = j; + } + } + } + int resposta = BFS(inix, iniy); + if (!resposta) cout << "NO\n"; + else { + cout << "YES\n"; + cout << resposta << endl; + vector caminho; + int i = fimx, j = fimy; + while (make_pair(i, j) != make_pair(inix, iniy)) { + caminho.push_back(path[i][j]); + if (path[i][j] == 'D') i--; + else if (path[i][j] == 'U') i++; + else if (path[i][j] == 'R') j--; + else j++; + } + for (int i = caminho.size()-1; i >= 0; i--) { + cout << caminho[i]; + } + cout << '\n'; + } +} \ No newline at end of file diff --git a/cses/graph/20 - Planets Queries II.cpp b/cses/graph/20 - Planets Queries II.cpp new file mode 100644 index 0000000..427f5e8 --- /dev/null +++ b/cses/graph/20 - Planets Queries II.cpp @@ -0,0 +1,108 @@ +// Planets Queries II +// +// Problem name: Planets Queries II +// Problem Link: https://cses.fi/problemset/task/1160 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +// You are playing a game consisting of n planets. +// Each planet has a teleporter to another planet (or the planet itself). +// You have to process q queries of the form: You are now on planet a and want to reach planet b. +// What is the minimum number of teleportations? + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 200100 +#define INF 1e17 +#define pb push_back +#define F first +#define S second + +using namespace std; +typedef long long ll; +typedef pair pii; +typedef pair pll; +mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); +const int M = 998244353; + +int tree[MAXN], ciclo[MAXN], id[MAXN], peso[MAXN], tab[MAXN][20], cor[MAXN], dep[MAXN], in[MAXN], x; + +int sobe(int node, int k) { + if (k < 0) return -1; + for (int i = 19; i >= 0; i--) { + if (k & (1<> n >> q; + for (int i = 1; i <= n; i++) { + cin >> tab[i][0]; + in[tab[i][0]]++; + } + for (int i = 1; i < 20; i++) { + for (int j = 1; j <= n; j++) tab[j][i] = tab[tab[j][i-1]][i-1]; + } + for (int i = 1; i <= n; i++) { + if (!cor[i]) dfs(i); + } + memset(cor, 0, sizeof(cor)); + for (int i = 1; i <= n; i++) { + if (!in[i]) dfs2(i); + } + int a, b; + for (int i = 0; i < q; i++) { + cin >> a >> b; + if (ciclo[a]) { + if (ciclo[b]) { + if (ciclo[a] == ciclo[b]) { + if (id[b] >= id[a]) cout << id[b] - id[a] << '\n'; + else cout << peso[ciclo[b]] + id[b] - id[a] << '\n'; + } + else cout << "-1\n"; + } + else if (!ciclo[b]) cout << "-1\n"; + } + else if (!ciclo[a]) { + if (!ciclo[b]) { + if (sobe(a, dep[a] - dep[b]) == b) cout << dep[a] - dep[b] << '\n'; + else cout << "-1\n"; + } + else if (ciclo[b]) { + if (ciclo[tree[a]] == ciclo[b]) { + if (id[b] >= id[tree[a]]) cout << id[b] - id[tree[a]] + dep[a] << '\n'; + else cout << peso[ciclo[b]] + id[b] - id[tree[a]] + dep[a] << '\n'; + } + else cout << "-1\n"; + } + } + } + return 0; +} \ No newline at end of file diff --git a/cses/graph/21 - Planets Cycles.cpp b/cses/graph/21 - Planets Cycles.cpp new file mode 100644 index 0000000..9fb730f --- /dev/null +++ b/cses/graph/21 - Planets Cycles.cpp @@ -0,0 +1,62 @@ +// Planets Cycles +// +// Problem name: Planets Cycles +// Problem Link: https://cses.fi/problemset/task/1751 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +// You are playing a game consisting of n planets. Each planet has a teleporter to another planet (or the planet itself). +// You start on a planet and then travel through teleporters until you reach a planet that you have already visited before. +// Your task is to calculate for each planet the number of teleportations there would be if you started on that planet. + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 200100 +#define INF 1e17 +#define pb push_back +#define F first +#define S second + +using namespace std; +typedef long long ll; +typedef pair pii; +typedef pair pll; +mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); +const int M = 998244353; + +int dist[MAXN], v[MAXN], cor[MAXN]; + +void dfs(int node) { + cor[node] = 1; + if (cor[v[node]] == 0) { + dfs(v[node]); + if (!dist[node]) dist[node] = dist[v[node]]+1; + } + else if (cor[v[node]] == 1) { + // ciclo + int atual = node, p = 0; + do { + p++; + atual = v[atual]; + } while (atual != node); + do { + dist[atual] = p; + atual = v[atual]; + } while (atual != node); + } + else { + dist[node] = dist[v[node]]+1; + } + cor[node] = 2; +} + +int main() { _ + int n; + cin >> n; + for (int i = 1; i <= n; i++) cin >> v[i]; + for (int i = 1; i <= n; i++) { + if (!cor[i]) dfs(i); + } + for (int i = 1; i <= n; i++) cout << dist[i] << ' '; + cout << '\n'; + return 0; +} \ No newline at end of file diff --git a/cses/graph/22 - Road Reparation.cpp b/cses/graph/22 - Road Reparation.cpp new file mode 100644 index 0000000..096aa8b --- /dev/null +++ b/cses/graph/22 - Road Reparation.cpp @@ -0,0 +1,67 @@ +// Road Reparation +// +// Problem name: Road Reparation +// Problem Link: https://cses.fi/problemset/task/1675 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 200100 +#define INF 1000000001 +#define pb push_back +#define F first +#define S second + +using namespace std; +typedef long long int ll; +typedef pair pii; +const int M = 1e9+7; + +int pai[MAXN], peso[MAXN]; +vector> v; + +int find(int a) { + if (pai[a] == a) return a; + return pai[a] = find(pai[a]); +} + +void join(int a, int b) { + a = find(a); + b = find(b); + if (a == b) return; + if (peso[a] > peso[b]) { + pai[b] = a; + } + if (peso[b] > peso[a]) { + pai[a] = b; + } + if (peso[a] == peso[b]) { + pai[a] = b; + peso[b]++; + } + return; +} + +int main () { _ + int n, m; + cin >> n >> m; + for (int i = 1; i <= n; i++) pai[i] = i; + for (int i = 0; i < m; i++) { + int a, b, c; + cin >> a >> b >> c; + v.pb({c, {a, b}}); + } + sort(v.begin(), v.end()); + ll ans = 0; + int count = 0; + for (int i = 0; i < m; i++) { + if (find(v[i].S.F) != find(v[i].S.S)) { + join(v[i].S.F, v[i].S.S); + ans += v[i].F; + count++; + } + } + if (count == n-1) cout << ans << '\n'; + else cout << "IMPOSSIBLE\n"; + return 0; +} \ No newline at end of file diff --git a/cses/graph/23 - Road Construction.cpp b/cses/graph/23 - Road Construction.cpp new file mode 100644 index 0000000..d4f8cea --- /dev/null +++ b/cses/graph/23 - Road Construction.cpp @@ -0,0 +1,64 @@ +// Road Construction +// +// Problem name: Road Construction +// Problem Link: https://cses.fi/problemset/task/1676 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 4000100 +#define INF 1000000001 +#define pb push_back +#define F first +#define S second + +using namespace std; +typedef long long int ll; +typedef pair pii; +const int M = 1e9+7; + +int pai[MAXN], sz[MAXN], peso[MAXN], comp, maxi; + +int find(int a) { + if (pai[a] == a) return a; + return pai[a] = find(pai[a]); +} + +void join(int a, int b) { + a = find(a); + b = find(b); + if (a == b) return; + comp--; + if (peso[a] > peso[b]) { + pai[b] = a; + sz[a] += sz[b]; + } + if (peso[b] > peso[a]) { + pai[a] = b; + sz[b] += sz[a]; + } + if (peso[a] == peso[b]) { + pai[a] = b; + sz[b] += sz[a]; + peso[b]++; + } + maxi = max({maxi, sz[a], sz[b]}); + return; +} + +int main () { _ + int n, m; + cin >> n >> m; + for (int i = 1; i <= n; i++) { + pai[i] = i; + sz[i] = 1; + } + comp = n, maxi = 1; + for (int i = 0; i < m; i++) { + int a, b; + cin >> a >> b; + join(a, b); + cout << comp << ' ' << maxi << '\n'; + } + return 0; +} \ No newline at end of file diff --git a/cses/graph/24 - Flight Routes Check.cpp b/cses/graph/24 - Flight Routes Check.cpp new file mode 100644 index 0000000..2b2b2f8 --- /dev/null +++ b/cses/graph/24 - Flight Routes Check.cpp @@ -0,0 +1,67 @@ +// Flight Routes Check +// +// Problem name: Flight Routes Check +// Problem Link: https://cses.fi/problemset/task/1682 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +// There are n cities and m flight connections. Your task is to check if +// you can travel from any city to any other city using the available flights. + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 100100 +#define INF 1e18 +#define pb push_back +#define F first +#define S second + +using namespace std; +typedef long long ll; +typedef pair pii; +typedef pair pll; +mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); +const int M = 1e9+7; + +int vis[MAXN], cnt = 0; +vector v[MAXN], w[MAXN], ord, c[MAXN]; + +void dfs1(int node) { + vis[node] = 1; + for (int x : v[node]) + if (!vis[x]) dfs1(x); + ord.pb(node); +} + +void dfs2(int node) { + vis[node] = 1; + c[cnt].pb(node); + for (int x : w[node]) + if (!vis[x]) dfs2(x); +} + +int main () { _ + int n, m, a, b; + cin >> n >> m; + for (int i = 0; i < m; i++) { + cin >> a >> b; + v[a].pb(b); + w[b].pb(a); + } + for (int i = 1; i <= n; i++) { + if (!vis[i]) dfs1(i); + } + memset(vis, 0, sizeof(vis)); + reverse(ord.begin(), ord.end()); + for (int x : ord) { + if (!vis[x]) { + cnt++; + dfs2(x); + } + } + if (cnt == 1) cout << "YES\n"; + else { + cout << "NO\n"; + cout << c[2][0] << ' ' << c[1][0] << '\n'; + } + return 0; +} \ No newline at end of file diff --git a/cses/graph/25 - Planets and Kingdoms.cpp b/cses/graph/25 - Planets and Kingdoms.cpp new file mode 100644 index 0000000..c48c770 --- /dev/null +++ b/cses/graph/25 - Planets and Kingdoms.cpp @@ -0,0 +1,67 @@ +// Planets and Kingdoms +// +// Problem name: Planets and Kingdoms +// Problem Link: https://cses.fi/problemset/task/1683 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +// A game has n planets, connected by m teleporters. +// Two planets a and b belong to the same kingdom exactly +// when there is a route both from a to b and from b to a. +// Your task is to determine for each planet its kingdom. + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 100100 +#define INF 1e18 +#define pb push_back +#define F first +#define S second + +using namespace std; +typedef long long ll; +typedef pair pii; +typedef pair pll; +mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); +const int M = 1e9+7; + +int vis[MAXN], cnt = 0, c[MAXN]; +vector v[MAXN], w[MAXN], ord; + +void dfs1(int node) { + vis[node] = 1; + for (int x : v[node]) + if (!vis[x]) dfs1(x); + ord.pb(node); +} + +void dfs2(int node) { + vis[node] = 1; + c[node] = cnt; + for (int x : w[node]) + if (!vis[x]) dfs2(x); +} + +int main () { _ + int n, m, a, b; + cin >> n >> m; + for (int i = 0; i < m; i++) { + cin >> a >> b; + v[a].pb(b); + w[b].pb(a); + } + for (int i = 1; i <= n; i++) { + if (!vis[i]) dfs1(i); + } + memset(vis, 0, sizeof(vis)); + reverse(ord.begin(), ord.end()); + for (int x : ord) { + if (!vis[x]) { + cnt++; + dfs2(x); + } + } + cout << cnt << '\n'; + for (int i = 1; i <= n; i++) cout << c[i] << ' '; + cout << '\n'; + return 0; +} \ No newline at end of file diff --git a/cses/graph/26 - Giant Pizza.cpp b/cses/graph/26 - Giant Pizza.cpp new file mode 100644 index 0000000..d056550 --- /dev/null +++ b/cses/graph/26 - Giant Pizza.cpp @@ -0,0 +1,99 @@ +// Giant Pizza +// +// Problem name: Giant Pizza +// Problem Link: https://cses.fi/problemset/task/1684 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +// Uolevi's family is going to order a large pizza and eat it together. +// A total of n family members will join the order, and there are m possible toppings. +// The pizza may have any number of toppings. +// Each family member gives two wishes concerning the toppings of the pizza. +// The wishes are of the form "topping x is good/bad". Your task is to choose the toppings so that at least one wish from everybody becomes true (a good topping is included in the pizza or a bad topping is not included). + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 200100 +#define INF 1e18 +#define pb push_back +#define F first +#define S second + +using namespace std; +typedef long long ll; +typedef pair pii; +typedef pair pll; +mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); +const int M = 1e9+7; + +vector v[MAXN], w[MAXN], ord, c[MAXN]; +int vis[MAXN], cnt = 0, cmp[MAXN], ans[MAXN]; + +void dfs1(int node) { + vis[node] = 1; + for (int x : v[node]) + if (!vis[x]) dfs1(x); + ord.pb(node); +} + +void dfs2(int node) { + cmp[node] = cnt; + c[cnt].pb(node); + vis[node] = 1; + for (int x : w[node]) + if (!vis[x]) dfs2(x); +} + +int main () { _ + int n, m; + cin >> n >> m; + for (int i = 0; i < n; i++) { + char a1, a2; + int aux1, aux2; + cin >> a1 >> aux1 >> a2 >> aux2; + if (a1 == '+' && a2 == '+') { + v[2*aux1+1].pb(2*aux2); + v[2*aux2+1].pb(2*aux1); + w[2*aux2].pb(2*aux1+1); + w[2*aux1].pb(2*aux2+1); + } + else if (a1 == '+' && a2 == '-') { + v[2*aux1+1].pb(2*aux2+1); + v[2*aux2].pb(2*aux1); + w[2*aux2+1].pb(2*aux1+1); + w[2*aux1].pb(2*aux2); + } + else if (a1 == '-' && a2 == '+') { + v[2*aux1].pb(2*aux2); + v[2*aux2+1].pb(2*aux1+1); + w[2*aux2].pb(2*aux1); + w[2*aux1+1].pb(2*aux2+1); + } + else if (a1 == '-' && a2 == '-') { + v[2*aux1].pb(2*aux2+1); + v[2*aux2].pb(2*aux1+1); + w[2*aux2+1].pb(2*aux1); + w[2*aux1+1].pb(2*aux2); + } + } + for (int i = 2; i <= 2*m+1; i++) + if (!vis[i]) dfs1(i); + reverse(ord.begin(), ord.end()); + memset(vis, 0, sizeof(vis)); + for (int x : ord) { + if (!vis[x]) { + cnt++; + dfs2(x); + } + } + bool ok = true; + for (int i = 2; i <= 2*m; i+=2) { + if (cmp[i] == cmp[i+1]) ok = false; + ans[i/2] = (cmp[i] > cmp[i+1]); + } + if (!ok) cout << "IMPOSSIBLE\n"; + else { + for (int i = 1; i <= m; i++) cout << (ans[i] ? '+' : '-') << ' '; + cout << '\n'; + } + return 0; +} \ No newline at end of file diff --git a/cses/graph/27 - Coin Collector.cpp b/cses/graph/27 - Coin Collector.cpp new file mode 100644 index 0000000..8dae1ed --- /dev/null +++ b/cses/graph/27 - Coin Collector.cpp @@ -0,0 +1,82 @@ +// Coin Collector +// +// Problem name: Coin Collector +// Problem Link: https://cses.fi/problemset/task/1686 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 100100 +#define INF 1e18 +#define pb push_back +#define F first +#define S second + +using namespace std; +typedef long long ll; +typedef pair pii; +typedef pair pll; +mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); +const int M = 1e9+7; + +int vis[MAXN], comp[MAXN], cnt = 0; +ll c1[MAXN], c2[MAXN], dp[MAXN], ans = 0; +vector v[MAXN], w[MAXN], nv[MAXN], ord; + +void dfs1(int node) { + vis[node] = 1; + for (int x : v[node]) + if (!vis[x]) dfs1(x); + ord.pb(node); +} + +void dfs2(int node) { + vis[node] = 1; + c2[cnt] += c1[node]; + comp[node] = cnt; + for (int x : w[node]) + if (!vis[x]) dfs2(x); +} + +void dfs3(int node) { + vis[node] = 1; + dp[node] = c2[node]; + for (int x : nv[node]) { + if (!vis[x]) dfs3(x); + dp[node] = max(dp[x] + c2[node], dp[node]); + } + ans = max(ans, dp[node]); +} + +int main () { _ + int n, m, a, b; + cin >> n >> m; + for (int i = 1; i <= n; i++) cin >> c1[i]; + for (int i = 0; i < m; i++) { + cin >> a >> b; + v[a].pb(b); + w[b].pb(a); + } + for (int i = 1; i <= n; i++) { + if (!vis[i]) dfs1(i); + } + memset(vis, 0, sizeof(vis)); + reverse(ord.begin(), ord.end()); + for (int x : ord) { + if (!vis[x]) { + cnt++; + dfs2(x); + } + } + for (int i = 1; i <= n; i++) { + for (int x : v[i]) { + if (comp[x] != comp[i]) nv[comp[i]].pb(comp[x]); + } + } + memset(vis, 0, sizeof(vis)); + for (int i = 1; i <= n; i++) { + if (!vis[i]) dfs3(i); + } + cout << ans << '\n'; + return 0; +} \ No newline at end of file diff --git a/cses/graph/28 - Mail Delivery.cpp b/cses/graph/28 - Mail Delivery.cpp new file mode 100644 index 0000000..ac18c69 --- /dev/null +++ b/cses/graph/28 - Mail Delivery.cpp @@ -0,0 +1,80 @@ +// Mail Delivery +// +// Problem name: Mail Delivery +// Problem Link: https://cses.fi/problemset/task/1691 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +// Your task is to deliver mail to the inhabitants of a city. For this reason, +// you want to find a route whose starting and ending point are the post office, +// and that goes through every street exactly once. + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 4000100 +#define INF 1000000001 +#define pb push_back +#define F first +#define S second + +using namespace std; +typedef long long int ll; +typedef pair pii; +const int M = 1e9+7; + +stack ans; +vector v[MAXN]; +int grau[MAXN], edge[MAXN]; + +void euler(int node) { + stack path; + path.push(node); + while (!path.empty()) { + int cur = path.top(); + while (!v[cur].empty() && edge[v[cur].back().S]) { + grau[cur]--; + v[cur].pop_back(); + } + if (!grau[cur]) { + ans.push(cur); + path.pop(); + continue; + } + pii next = v[cur].back(); + v[cur].pop_back(); + grau[cur]--; + edge[next.S] = 1; + path.push(next.F); + } +} + +int main () { _ + int n, m; + cin >> n >> m; + for (int i = 0; i < m; i++) { + int a, b; + cin >> a >> b; + v[a].pb({b, i}); + v[b].pb({a, i}); + grau[a]++, grau[b]++; + } + bool ok = true; + for (int i = 1; i <= n; i++) { + ok &= (grau[i] % 2 == 0); + } + if (!ok) cout << "IMPOSSIBLE\n"; + else { + euler(1); + for (int i = 0; i < m; i++) { + ok &= edge[i]; + } + if (!ok) cout << "IMPOSSIBLE\n"; + else { + while (!ans.empty()) { + cout << ans.top() << ' '; + ans.pop(); + } + cout << '\n'; + } + } + return 0; +} \ No newline at end of file diff --git a/cses/graph/29 - De Bruijn Sequence.cpp b/cses/graph/29 - De Bruijn Sequence.cpp new file mode 100644 index 0000000..a2032d0 --- /dev/null +++ b/cses/graph/29 - De Bruijn Sequence.cpp @@ -0,0 +1,61 @@ +// De Bruijn Sequence +// +// Problem name: De Bruijn Sequence +// Problem Link: https://cses.fi/problemset/task/1692 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +// Your task is to construct a minimum-length bit string that contains all possible substrings of length n. +// For example, when n=2, the string 00110 is a valid solution, because its substrings of length 2 are 00, 01, 10 and 11. + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 4000100 +#define INF 1000000001 +#define pb push_back +#define F first +#define S second + +using namespace std; +typedef long long int ll; +typedef pair pii; +const int M = 1e9+7; + +vector v[MAXN]; +string ans; +int grau[MAXN], n, start = -1; + +void euler(int node) { + stack> path; + path.push({node, ' '}); + while (!path.empty()) { + pair cur = path.top(); + if (!grau[cur.F]) { + if (start == -1) start = cur.F; + ans += cur.S; + path.pop(); + } + else { + int next = v[cur.F].back(); + v[cur.F].pop_back(); + path.push({next, (next&1 ? '1' : '0')}); + grau[cur.F]--; + } + } +} + +int main () { _ + cin >> n; + for (int i = 0; i < (1<<(n-1)); i++) { + int next = i<<1 & ((1<<(n-1)) - 1); + v[i].pb(next); + v[i].pb(next+1); + grau[i] = 2; + } + euler(0); + ans.pop_back(); + for (int i = 0; i < n-1; i++) { + ans += (start & (1 << i) ? '1' : '0'); + } + cout << ans << '\n'; + return 0; +} \ No newline at end of file diff --git a/cses/graph/3 - Building Roads.cpp b/cses/graph/3 - Building Roads.cpp new file mode 100644 index 0000000..bb8aabc --- /dev/null +++ b/cses/graph/3 - Building Roads.cpp @@ -0,0 +1,63 @@ +// Building Roads +// +// Problem name: Building Roads +// Problem Link: https://cses.fi/problemset/task/1666 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 100100 +#define INF 1000000 + +using namespace std; +typedef long long int lli; +typedef pair pii; +const int mod = 1e9+7; + +int pai[MAXN], n, m; +bool check[MAXN]; +vector resp; + +int find(int x) { + if (pai[x] == x) return x; + return pai[x] = find(pai[x]); +} + +void join(int a, int b) { + int pai1 = find(a); + int pai2 = find(b); + + if (pai1 == pai2) return; + if (pai1 == 1) { + pai[pai2] = pai1; + } + else pai[pai1] = pai2; +} + +int main() { _ + int resp = 0; + queue ans; + cin >> n >> m; + int a, b; + for (int i = 1; i <= n; i++) { + pai[i] = i; + } + for (int i = 0; i < m; i++) { + cin >> a >> b; + join(a, b); + } + int conec = 1; + for (int i = 2; i <= n; i++) { + if (find(i) != conec) { + resp++; + ans.push({1, i}); + join(1, i); + } + } + cout << resp << endl; + while(!ans.empty()) { + cout << ans.front().first << " " << ans.front().second << endl; + ans.pop(); + } + return 0; +} \ No newline at end of file diff --git a/cses/graph/30 - Teleporters Path.cpp b/cses/graph/30 - Teleporters Path.cpp new file mode 100644 index 0000000..d1c01a0 --- /dev/null +++ b/cses/graph/30 - Teleporters Path.cpp @@ -0,0 +1,74 @@ +// Teleporters Path +// +// Problem name: Teleporters Path +// Problem Link: https://cses.fi/problemset/task/1693 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +// A game has n levels and m teleportes between them. +// You win the game if you move from level 1 to level n using every teleporter exactly once. +// Can you win the game, and what is a possible way to do it? + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 4000100 +#define INF 1000000001 +#define pb push_back +#define F first +#define S second + +using namespace std; +typedef long long int ll; +typedef pair pii; +const int M = 1e9+7; + +stack ans; +vector v[MAXN]; +int grau[MAXN], num[MAXN], edge[MAXN]; + +void euler(int node) { + stack path; + path.push(node); + while (!path.empty()) { + int cur = path.top(); + if (!num[cur]) { + ans.push(cur); + path.pop(); + } + else { + pii next = v[cur].back(); + v[cur].pop_back(); + num[cur]--; + edge[next.S] = 1; + path.push(next.F); + } + } +} + +int main () { _ + int n, m; + cin >> n >> m; + for (int i = 0; i < m; i++) { + int a, b; + cin >> a >> b; + v[a].pb({b, i}); + grau[a]++; + grau[b]--; + num[a]++; + } + bool valid = (grau[1] == 1 && grau[n] == -1); + for (int i = 2; i < n; i++) valid &= (grau[i] == 0); + if (!valid) cout << "IMPOSSIBLE\n"; + else { + euler(1); + for (int i = 0; i < m; i++) valid &= edge[i]; + if (!valid) cout << "IMPOSSIBLE\n"; + else { + while (!ans.empty()) { + cout << ans.top() << ' '; + ans.pop(); + } + cout << '\n'; + } + } + return 0; +} \ No newline at end of file diff --git a/cses/graph/31 - Hamiltonian Flights.cpp b/cses/graph/31 - Hamiltonian Flights.cpp new file mode 100644 index 0000000..33d936d --- /dev/null +++ b/cses/graph/31 - Hamiltonian Flights.cpp @@ -0,0 +1,49 @@ +// Hamiltonian Flights +// +// Problem name: Hamiltonian Flights +// Problem Link: https://cses.fi/problemset/task/1690 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +// There are n cities and m flight connections between them. +// You want to travel from Syrjälä to Lehmälä so that you visit each city exactly once. +// How many possible routes are there? + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 4000100 +#define INF 1000000001 +#define pb push_back +#define F first +#define S second + +using namespace std; +typedef long long int ll; +typedef pair pii; +const int M = 1e9+7; + +int mat[25][25], dp[1100000][25]; + +int main () { _ + int n, m; + cin >> n >> m; + for (int i = 0; i < m; i++) { + int a, b; + cin >> a >> b; + mat[a][b]++; + } + dp[1][1] = 1; + for (int i = 1; i < (1<= M) dp[i ^ (1< +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 4000100 +#define INF 1000000001 +#define pb push_back +#define F first +#define S second + +using namespace std; +typedef long long int ll; +typedef pair pii; +const int M = 1e9+7; + +int dx[8] = {2, 2, -2, -2, 1, -1, 1, -1}, dy[8] = {1, -1, 1, -1, 2, 2, -2, -2}; +int mat[10][10]; + +bool valid(int x, int y) { return (x >= 0 && y >= 0 && x < 8 && y < 8 && !mat[x][y]); } + +int count(int x, int y) { + int resp = 0; + for (int i = 0; i < 8; i++) { + resp += valid(x+dx[i], y+dy[i]); + } + return resp; +} + +bool dfs(int x, int y, int pos) { + if (pos == 64) return true; + vector> v; + for (int i = 0; i < 8; i++) { + if (valid(x+dx[i], y+dy[i])) { + v.pb({count(x+dx[i], y+dy[i]), {x+dx[i], y+dy[i]}}); + } + } + sort(v.begin(), v.end()); + for (int i = 0; i < (int)v.size(); i++) { + mat[v[i].S.F][v[i].S.S] = pos+1; + if (dfs(v[i].S.F, v[i].S.S, pos+1)) return true; + mat[v[i].S.F][v[i].S.S] = 0; + } + return false; +} + +int main () { _ + int x, y; + cin >> x >> y; + x--, y--; + mat[y][x] = 1; + dfs(y, x, 1); + for (int i = 0; i < 8; i++) { + for (int j = 0; j < 8; j++) { + cout << mat[i][j] << ' '; + } + cout << '\n'; + } + return 0; +} \ No newline at end of file diff --git a/cses/graph/33 - Download Speed.cpp b/cses/graph/33 - Download Speed.cpp new file mode 100644 index 0000000..c724850 --- /dev/null +++ b/cses/graph/33 - Download Speed.cpp @@ -0,0 +1,187 @@ +// Download Speed +// +// Problem name: Download Speed +// Problem Link: https://cses.fi/problemset/task/1694 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +#include +using namespace std; +#define int long long + +// A structure to represent a edge between +// two vertex +struct Edge +{ + int v ; // Vertex v (or "to" vertex) + // of a directed edge u-v. "From" + // vertex u can be obtained using + // index in adjacent array. + + int flow ; // flow of data in edge + + int C; // capacity + + int rev ; // To store index of reverse + // edge in adjacency list so that + // we can quickly find it. +}; + +// Residual Graph +class Graph +{ + int V; // number of vertex + int *level ; // stores level of a node + vector< Edge > *adj; +public : + Graph(int V) + { + adj = new vector[V]; + this->V = V; + level = new int[V]; + } + + // add edge to the graph + void addEdge(int u, int v, int C) + { + // Forward edge : 0 flow and C capacity + Edge a{v, 0, C, adj[v].size()}; + + // Back edge : 0 flow and 0 capacity + Edge b{u, 0, 0, adj[u].size()}; + + adj[u].push_back(a); + adj[v].push_back(b); // reverse edge + } + + bool BFS(int s, int t); + int sendFlow(int s, int flow, int t, int ptr[]); + int DinicMaxflow(int s, int t); +}; + +// Finds if more flow can be sent from s to t. +// Also assigns levels to nodes. +bool Graph::BFS(int s, int t) +{ + for (int i = 0 ; i < V ; i++) + level[i] = -1; + + level[s] = 0; // Level of source vertex + + // Create a queue, enqueue source vertex + // and mark source vertex as visited here + // level[] array works as visited array also. + list< int > q; + q.push_back(s); + + vector::iterator i ; + while (!q.empty()) + { + int u = q.front(); + q.pop_front(); + for (i = adj[u].begin(); i != adj[u].end(); i++) + { + Edge &e = *i; + if (level[e.v] < 0 && e.flow < e.C) + { + // Level of current vertex is, + // level of parent + 1 + level[e.v] = level[u] + 1; + + q.push_back(e.v); + } + } + } + + // IF we can not reach to the sink we + // return false else true + return level[t] < 0 ? false : true ; +} + +// A DFS based function to send flow after BFS has +// figured out that there is a possible flow and +// constructed levels. This function called multiple +// times for a single call of BFS. +// flow : Current flow send by parent function call +// start[] : To keep track of next edge to be explored. +// start[i] stores count of edges explored +// from i. +// u : Current vertex +// t : Sink +int Graph::sendFlow(int u, int flow, int t, int start[]) +{ + // Sink reached + if (u == t) + return flow; + + // Traverse all adjacent edges one -by - one. + for ( ; start[u] < adj[u].size(); start[u]++) + { + // Pick next edge from adjacency list of u + Edge &e = adj[u][start[u]]; + + if (level[e.v] == level[u]+1 && e.flow < e.C) + { + // find minimum flow from u to t + int curr_flow = min(flow, e.C - e.flow); + + int temp_flow = sendFlow(e.v, curr_flow, t, start); + + // flow is greater than zero + if (temp_flow > 0) + { + // add flow to current edge + e.flow += temp_flow; + + // subtract flow from reverse edge + // of current edge + adj[e.v][e.rev].flow -= temp_flow; + return temp_flow; + } + } + } + + return 0; +} + +// Returns maximum flow in graph +int Graph::DinicMaxflow(int s, int t) +{ + // Corner case + if (s == t) + return -1; + + int total = 0; // Initialize result + + // Augment the flow while there is path + // from source to sink + while (BFS(s, t) == true) + { + // store how many edges are visited + // from V { 0 to V } + int *start = new int[V+1] {0}; + + // while flow is not zero in graph from S to D + while (int flow = sendFlow(s, INT_MAX, t, start)) + + // Add path flow to overall flow + total += flow; + } + + // return maximum flow + return total; +} + +// Driver Code +int32_t main() { + int n, m; + cin >> n >> m; + Graph g(n); + for (int i = 0; i < m; i++) { + int a, b, c; + cin >> a >> b >> c; + a--, b--; + g.addEdge(a, b, c); + } + cout << g.DinicMaxflow(0, n-1) << '\n'; + return 0; +} \ No newline at end of file diff --git a/cses/graph/34 - Police Chase.cpp b/cses/graph/34 - Police Chase.cpp new file mode 100644 index 0000000..d8e3847 --- /dev/null +++ b/cses/graph/34 - Police Chase.cpp @@ -0,0 +1,128 @@ +// Police Chase +// +// Problem name: Police Chase +// Problem Link: https://cses.fi/problemset/task/1695 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +// Kaaleppi has just robbed a bank and is now heading to the harbor. +// However, the police wants to stop him by closing some streets of the city. +// What is the minimum number of streets that should be closed so that +// there is no route between the bank and the harbor? + +#include + +using namespace std; +using ll = long long; +using pii = pair; +using pll = pair; + +mt19937 rng((int) chrono::steady_clock::now().time_since_epoch().count()); + +const int MOD = 1e9 + 7; +const int MAXN = 2e5 + 5; +const int INF = 1e9; + +// Dinic +// +// O(min(m * max_flow, n^2 m)) +// Grafo com capacidades 1 -> O(sqrt(n)*m) +struct dinic { + const bool scaling = false; + int lim; + struct edge { + int to, cap, rev, flow; + bool res; + edge(int to_, int cap_, int rev_, bool res_) + : to(to_), cap(cap_), rev(rev_), flow(0), res(res_) {} + }; + + vector> g; + vector lev, beg; + ll F; + dinic(int n) : g(n), F(0) {} + + void add(int a, int b, int c) { + g[a].emplace_back(b, c, g[b].size(), false); + g[b].emplace_back(a, 0, g[a].size()-1, true); + } + bool bfs(int s, int t) { + lev = vector(g.size(), -1); lev[s] = 0; + beg = vector(g.size(), 0); + queue q; q.push(s); + while (q.size()) { + int u = q.front(); q.pop(); + for (auto& i : g[u]) { + if (lev[i.to] != -1 or (i.flow == i.cap)) continue; + if (scaling and i.cap - i.flow < lim) continue; + lev[i.to] = lev[u] + 1; + q.push(i.to); + } + } + return lev[t] != -1; + } + int dfs(int v, int s, int f = INF) { + if (!f or v == s) return f; + for (int& i = beg[v]; i < g[v].size(); i++) { + auto& e = g[v][i]; + if (lev[e.to] != lev[v] + 1) continue; + int foi = dfs(e.to, s, min(f, e.cap - e.flow)); + if (!foi) continue; + e.flow += foi, g[e.to][e.rev].flow -= foi; + return foi; + } + return 0; + } + ll max_flow(int s, int t) { + for (lim = scaling ? (1<<30) : 1; lim; lim /= 2) + while (bfs(s, t)) while (int ff = dfs(s, t)) F += ff; + return F; + } + + // arestas com fluxo + vector flow_edges() { + vector ans; + int n = g.size(); + for (int i = 0; i < n; i++) { + for (auto edge : g[i]) { + if (!edge.res && edge.flow) + ans.emplace_back(i, edge.to); + } + } + return ans; + } + + // arestas no min cut + vector cut_edges(int s, int t) { + max_flow(s, t); + vector cut; + vector vis(g.size(), 0), st = {s}; + vis[s] = 1; + while (st.size()) { + int u = st.back(); st.pop_back(); + for (auto e : g[u]) if (!vis[e.to] and e.flow < e.cap) + vis[e.to] = 1, st.push_back(e.to); + } + for (int i = 0; i < g.size(); i++) for (auto e : g[i]) + if (vis[i] and !vis[e.to] and !e.res) cut.emplace_back(i, e.to); + return cut; + } +}; + +int main() { + ios::sync_with_stdio(false); + cin.tie(0); + int n, m; + cin >> n >> m; + dinic ber(n); + for (int i = 0; i < m; i++) { + int a, b; + cin >> a >> b; + a--, b--; + ber.add(a, b, 1); + ber.add(b, a, 1); + } + vector ed = ber.cut_edges(0, n - 1); + cout << ber.max_flow(0, n - 1) << '\n'; + for (auto x : ed) cout << x.first + 1 << ' ' << x.second + 1 << '\n'; + return 0; +} \ No newline at end of file diff --git a/cses/graph/35 - School Dance.cpp b/cses/graph/35 - School Dance.cpp new file mode 100644 index 0000000..cb673ba --- /dev/null +++ b/cses/graph/35 - School Dance.cpp @@ -0,0 +1,135 @@ +// School Dance +// +// Problem name: School Dance +// Problem Link: https://cses.fi/problemset/task/1696 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +// There are n boys and m girls in a school. Next week a school dance will be organized. +// A dance pair consists of a boy and a girl, and there are k potential pairs. +// Your task is to find out the maximum number of dance pairs and show how this number can be achieved. + +#include + +using namespace std; +using ll = long long; +using pii = pair; +using pll = pair; + +mt19937 rng((int) chrono::steady_clock::now().time_since_epoch().count()); + +const int MOD = 1e9 + 7; +const int MAXN = 2e5 + 5; +const int INF = 1e9; + +// Dinic +// +// O(min(m * max_flow, n^2 m)) +// Grafo com capacidades 1 -> O(sqrt(n)*m) +struct dinic { + const bool scaling = false; + int lim; + struct edge { + int to, cap, rev, flow; + bool res; + edge(int to_, int cap_, int rev_, bool res_) + : to(to_), cap(cap_), rev(rev_), flow(0), res(res_) {} + }; + + vector> g; + vector lev, beg; + ll F; + dinic(int n) : g(n), F(0) {} + + void add(int a, int b, int c) { + g[a].emplace_back(b, c, g[b].size(), false); + g[b].emplace_back(a, 0, g[a].size()-1, true); + } + bool bfs(int s, int t) { + lev = vector(g.size(), -1); lev[s] = 0; + beg = vector(g.size(), 0); + queue q; q.push(s); + while (q.size()) { + int u = q.front(); q.pop(); + for (auto& i : g[u]) { + if (lev[i.to] != -1 or (i.flow == i.cap)) continue; + if (scaling and i.cap - i.flow < lim) continue; + lev[i.to] = lev[u] + 1; + q.push(i.to); + } + } + return lev[t] != -1; + } + int dfs(int v, int s, int f = INF) { + if (!f or v == s) return f; + for (int& i = beg[v]; i < g[v].size(); i++) { + auto& e = g[v][i]; + if (lev[e.to] != lev[v] + 1) continue; + int foi = dfs(e.to, s, min(f, e.cap - e.flow)); + if (!foi) continue; + e.flow += foi, g[e.to][e.rev].flow -= foi; + return foi; + } + return 0; + } + ll max_flow(int s, int t) { + for (lim = scaling ? (1<<30) : 1; lim; lim /= 2) + while (bfs(s, t)) while (int ff = dfs(s, t)) F += ff; + return F; + } + + // arestas com fluxo + vector flow_edges() { + vector ans; + int n = g.size(); + for (int i = 0; i < n; i++) { + for (auto edge : g[i]) { + if (!edge.res && edge.flow) + ans.emplace_back(i, edge.to); + } + } + return ans; + } + + // arestas no min cut + vector cut_edges(int s, int t) { + max_flow(s, t); + vector cut; + vector vis(g.size(), 0), st = {s}; + vis[s] = 1; + while (st.size()) { + int u = st.back(); st.pop_back(); + for (auto e : g[u]) if (!vis[e.to] and e.flow < e.cap) + vis[e.to] = 1, st.push_back(e.to); + } + for (int i = 0; i < g.size(); i++) for (auto e : g[i]) + if (vis[i] and !vis[e.to] and !e.res) cut.emplace_back(i, e.to); + return cut; + } +}; + +int main() { + ios::sync_with_stdio(false); + cin.tie(0); + int n, m, k; + cin >> n >> m >> k; + int src = n + m, snk = n + m + 1; + dinic ber(snk + 1); + for (int i = 0; i < k; i++) { + int a, b; + cin >> a >> b; + a--, b--; + ber.add(a, n + b, 1); + } + for (int i = 0; i < n; i++) { + ber.add(src, i, 1); + } + for (int i = 0; i < m; i++) { + ber.add(i + n, snk, 1); + } + cout << ber.max_flow(src, snk) << '\n'; + vector ed = ber.flow_edges(); + for (auto x : ed) { + if (x.first != src && x.second != snk) cout << x.first + 1 << ' ' << x.second - n + 1 << '\n'; + } + return 0; +} \ No newline at end of file diff --git a/cses/graph/36 - Distinct Routes.cpp b/cses/graph/36 - Distinct Routes.cpp new file mode 100644 index 0000000..909e51e --- /dev/null +++ b/cses/graph/36 - Distinct Routes.cpp @@ -0,0 +1,152 @@ +// Distinct Routes +// +// Problem name: Distinct Routes +// Problem Link: https://cses.fi/problemset/task/1711 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +// A game consists of n rooms and m teleporters. +// At the beginning of each day, you start in room 1 and you have to reach room n. +// You can use each teleporter at most once during the game. +// How many days can you play if you choose your routes optimally? + +#include + +using namespace std; +using ll = long long; +using pii = pair; +using pll = pair; + +mt19937 rng((int) chrono::steady_clock::now().time_since_epoch().count()); + +const int MOD = 1e9 + 7; +const int MAXN = 2e5 + 5; +const int INF = 1e9; + +// Dinic +// +// O(min(m * max_flow, n^2 m)) +// Grafo com capacidades 1 -> O(sqrt(n)*m) +struct dinic { + const bool scaling = false; + int lim; + struct edge { + int to, cap, rev, flow; + bool res; + edge(int to_, int cap_, int rev_, bool res_) + : to(to_), cap(cap_), rev(rev_), flow(0), res(res_) {} + }; + + vector> g; + vector lev, beg; + ll F; + dinic(int n) : g(n), F(0) {} + + void add(int a, int b, int c) { + g[a].emplace_back(b, c, g[b].size(), false); + g[b].emplace_back(a, 0, g[a].size()-1, true); + } + bool bfs(int s, int t) { + lev = vector(g.size(), -1); lev[s] = 0; + beg = vector(g.size(), 0); + queue q; q.push(s); + while (q.size()) { + int u = q.front(); q.pop(); + for (auto& i : g[u]) { + if (lev[i.to] != -1 or (i.flow == i.cap)) continue; + if (scaling and i.cap - i.flow < lim) continue; + lev[i.to] = lev[u] + 1; + q.push(i.to); + } + } + return lev[t] != -1; + } + int dfs(int v, int s, int f = INF) { + if (!f or v == s) return f; + for (int& i = beg[v]; i < g[v].size(); i++) { + auto& e = g[v][i]; + if (lev[e.to] != lev[v] + 1) continue; + int foi = dfs(e.to, s, min(f, e.cap - e.flow)); + if (!foi) continue; + e.flow += foi, g[e.to][e.rev].flow -= foi; + return foi; + } + return 0; + } + ll max_flow(int s, int t) { + for (lim = scaling ? (1<<30) : 1; lim; lim /= 2) + while (bfs(s, t)) while (int ff = dfs(s, t)) F += ff; + return F; + } + + // arestas com fluxo + vector flow_edges(int s, int t) { + max_flow(s, t); + vector ans; + int n = g.size(); + for (int i = 0; i < n; i++) { + for (auto edge : g[i]) { + if (!edge.res && edge.flow) + ans.emplace_back(i, edge.to); + } + } + return ans; + } + + // arestas no min cut + vector cut_edges(int s, int t) { + max_flow(s, t); + vector cut; + vector vis(g.size(), 0), st = {s}; + vis[s] = 1; + while (st.size()) { + int u = st.back(); st.pop_back(); + for (auto e : g[u]) if (!vis[e.to] and e.flow < e.cap) + vis[e.to] = 1, st.push_back(e.to); + } + for (int i = 0; i < g.size(); i++) for (auto e : g[i]) + if (vis[i] and !vis[e.to] and !e.res) cut.emplace_back(i, e.to); + return cut; + } +}; + +vector v[505], caminho; +int ma[505][505], n, m; + +void dfs(int node) { + caminho.push_back(node); + for (int x : v[node]) { + if (!ma[node][x]) { + ma[node][x] = 1; + dfs(x); + break; + } + } +} + +int main() { + ios::sync_with_stdio(false); + cin.tie(0); + cin >> n >> m; + dinic ber(n); + for (int i = 0; i < m; i++) { + int a, b; + cin >> a >> b; + a--, b--; + ber.add(a, b, 1); + } + int tot = ber.max_flow(0, n - 1); + cout << tot << '\n'; + vector ed = ber.flow_edges(0, n - 1); + for (auto x : ed) { + v[x.first].push_back(x.second); + } + while (tot--) { + dfs(0); + cout << caminho.size() << '\n'; + for (int x : caminho) cout << x + 1 << ' '; + cout << '\n'; + caminho.clear(); + } + + return 0; +} \ No newline at end of file diff --git a/cses/graph/4 - Message Route.cpp b/cses/graph/4 - Message Route.cpp new file mode 100644 index 0000000..5b77179 --- /dev/null +++ b/cses/graph/4 - Message Route.cpp @@ -0,0 +1,70 @@ +// Message Route +// +// Problem name: Message Route +// Problem Link: https://cses.fi/problemset/task/1667 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 100100 +#define INF 1000000 +#define PB push_back +#define F first +#define S second + +using namespace std; +typedef long long int lli; +typedef pair pii; +const int mod = 1e9+7; + +int n, m, dist[MAXN], go[MAXN]; +vector vizinhos[MAXN]; + +void dijkstra() { + for (int i = 2; i <= n; i++) dist[i] = INF; + priority_queue, greater> fila; + dist[1] = 1; + fila.push({dist[1], 1}); + while (!fila.empty()) { + int atual = fila.top().S; + int d = fila.top().F; + fila.pop(); + if (d > dist[atual]) continue; + for (int i = 0; i < (int)vizinhos[atual].size(); i++) { + int prox = vizinhos[atual][i]; + if (dist[prox] > 1 + dist[atual]) { + dist[prox] = 1 + dist[atual]; + fila.push({dist[prox], prox}); + go[prox] = atual; + } + } + } +} + +int main() { _ + int a, b; + cin >> n >> m; + for (int i = 0; i < m; i++) { + cin >> a >> b; + vizinhos[a].PB(b); + vizinhos[b].PB(a); + } + dijkstra(); + if (dist[n] == INF) cout << "IMPOSSIBLE" << endl; + else { + cout << dist[n] << endl; + int atual = n; + stack ans; + ans.push(atual); + while (atual != 1) { + ans.push(go[atual]); + atual = go[atual]; + } + while (!ans.empty()) { + cout << ans.top() << " "; + ans.pop(); + } + cout << endl; + } + return 0; +} \ No newline at end of file diff --git a/cses/graph/5 - Building Teams.cpp b/cses/graph/5 - Building Teams.cpp new file mode 100644 index 0000000..6f9135f --- /dev/null +++ b/cses/graph/5 - Building Teams.cpp @@ -0,0 +1,56 @@ +// Building Teams +// +// Problem name: Building Teams +// Problem Link: https://cses.fi/problemset/task/1668 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 100100 +#define INF 1000000 +#define PB push_back +#define F first +#define S second + +using namespace std; +typedef long long int lli; +typedef pair pii; +const int mod = 1e9+7; + +int n, m, id, resp[MAXN]; +vector viz[MAXN]; +bool check[MAXN], ber; + +void DFS(int node, int z) { + check[node] = true; + resp[node] = z+1; + for (int i = 0; i < (int)viz[node].size(); i++) { + int atual = viz[node][i]; + if (!check[atual]) DFS(atual, 1-z); + else if (resp[atual] == resp[node]) ber = true; + } +} + +int main() { _ + int a, b; + cin >> n >> m; + for (int i = 0; i < m; i++) { + cin >> a >> b; + viz[a].PB(b); + viz[b].PB(a); + } + id = 0; + for (int i = 1; i <= n; i++) { + if (!check[i]) { + DFS(i, 0); + } + } + if (!ber) { + for (int i = 1; i <= n; i++) { + cout << resp[i] << " "; + } + cout << endl; + } + else cout << "IMPOSSIBLE" << endl; + return 0; +} \ No newline at end of file diff --git a/cses/graph/6 - Round Trip.cpp b/cses/graph/6 - Round Trip.cpp new file mode 100644 index 0000000..926916b --- /dev/null +++ b/cses/graph/6 - Round Trip.cpp @@ -0,0 +1,73 @@ +// Round Trip +// +// Problem name: Round Trip +// Problem Link: https://cses.fi/problemset/task/1669 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 100100 +#define INF 1000000 +#define PB push_back +#define F first +#define S second + +using namespace std; +typedef long long int lli; +typedef pair pii; +const int mod = 1e9+7; + +int n, m, go[MAXN], inicio; +vector viz[MAXN], resp; +bool check[MAXN], ber; + +void DFS(int node, int pai) { + check[node] = true; + for (int i = 0; i < (int)viz[node].size(); i++) { + int atual = viz[node][i]; + if (!check[atual]) { + if (!ber) go[atual] = node; + DFS(atual, node); + } + else if (atual != pai and !ber) { + ber = true; + inicio = atual; + go[atual] = node; + } + } +} + +int main() { _ + int a, b; + cin >> n >> m; + for (int i = 0; i < m; i++) { + cin >> a >> b; + viz[a].PB(b); + viz[b].PB(a); + } + for (int i = 1; i <= n; i++) { + if (!check[i]) { + resp.PB(i); + DFS(i, 0); + } + if (ber) break; + } + if (ber) { + stack ans; + ans.push(inicio); + int atual = go[inicio]; + while (atual != inicio) { + ans.push(atual); + atual = go[atual]; + } + ans.push(atual); + cout << (int)ans.size() << endl; + while (!ans.empty()) { + cout << ans.top() << " "; + ans.pop(); + } + cout << endl; + } + else cout << "IMPOSSIBLE" << endl; + return 0; +} \ No newline at end of file diff --git a/cses/graph/7 - Monsters.cpp b/cses/graph/7 - Monsters.cpp new file mode 100644 index 0000000..fa90bb9 --- /dev/null +++ b/cses/graph/7 - Monsters.cpp @@ -0,0 +1,127 @@ +// Monsters +// +// Problem name: Monsters +// Problem Link: https://cses.fi/problemset/task/1194 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 1010 +#define INF 1000000 +#define PB push_back +#define F first +#define S second + +using namespace std; +typedef long long int lli; +typedef pair pii; +const int mod = 1e9+7; + +int n, m, dist[MAXN][MAXN]; +pii go[MAXN][MAXN], a, A; +char v[MAXN][MAXN]; +bool ber, check[MAXN][MAXN]; +queue fila; +queue> qu; + +void BFS_multi() { + while(!fila.empty()) { + A = fila.front(); + fila.pop(); + check[A.F][A.S] = true; + if (A.F + 1 < n && !check[A.F+1][A.S] && v[A.F+1][A.S] != '#') { + dist[A.F+1][A.S] = min(dist[A.F+1][A.S], 1+dist[A.F][A.S]); + fila.push({A.F+1, A.S}); + check[A.F+1][A.S] = true; + } + if (A.F - 1 >= 0 && !check[A.F-1][A.S] && v[A.F-1][A.S] != '#') { + dist[A.F-1][A.S] = min(dist[A.F-1][A.S], 1+dist[A.F][A.S]); + fila.push({A.F-1, A.S}); + check[A.F-1][A.S] = true; + } + if (A.S + 1 < m && !check[A.F][A.S+1] && v[A.F][A.S+1] != '#') { + dist[A.F][A.S+1] = min(dist[A.F][A.S+1], 1+dist[A.F][A.S]); + fila.push({A.F, A.S+1}); + check[A.F][A.S+1] = true; + } + if (A.S - 1 >= 0 && !check[A.F][A.S-1] && v[A.F][A.S-1] != '#') { + dist[A.F][A.S-1] = min(dist[A.F][A.S-1], 1+dist[A.F][A.S]); + fila.push({A.F, A.S-1}); + check[A.F][A.S-1] = true; + } + } +} + +pii BFS() { + while (!qu.empty()) { + A = qu.front().F; + if (A.F == 0 || A.F == n-1 || A.S == 0 || A.S == m-1) { + return A; + } + int D = qu.front().S; + qu.pop(); + check[A.F][A.S] = true; + if (A.F + 1 < n && !check[A.F+1][A.S] && dist[A.F+1][A.S] > D+1 && v[A.F+1][A.S] != '#') { + go[A.F+1][A.S] = A; + qu.push(make_pair(make_pair(A.F+1, A.S), D+1)); + check[A.F+1][A.S] = true; + } + if (A.F - 1 >= 0 && !check[A.F-1][A.S] && dist[A.F-1][A.S] > D+1 && v[A.F-1][A.S] != '#') { + go[A.F-1][A.S] = A; + qu.push(make_pair(make_pair(A.F-1, A.S), D+1)); + check[A.F-1][A.S] = true; + } + if (A.S + 1 < m && !check[A.F][A.S+1] && dist[A.F][A.S+1] > D+1 && v[A.F][A.S+1] != '#') { + go[A.F][A.S+1] = A; + qu.push(make_pair(make_pair(A.F, A.S+1), D+1)); + check[A.F][A.S+1] = true; + } + if (A.S - 1 >= 0 && !check[A.F][A.S-1] && dist[A.F][A.S-1] > D+1 && v[A.F][A.S-1] != '#') { + go[A.F][A.S-1] = A; + qu.push(make_pair(make_pair(A.F, A.S-1), D+1)); + check[A.F][A.S-1] = true; + } + } + return {-1, -1}; +} + +int main() { _ + memset(go, -1, sizeof(go)); + cin >> n >> m; + int resp = 0; + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + cin >> v[i][j]; + if (v[i][j] == 'M') { + dist[i][j] = 0; + fila.push({i, j}); + } + else dist[i][j] = INF; + if (v[i][j] == 'A') a = {i, j}; + } + } + BFS_multi(); + memset(check, false, sizeof(check)); + qu.push({a, 0}); + pii fim = BFS(); + if (fim.F == -1) cout << "NO" << endl; + else { + cout << "YES" << endl; + stack ans; + while(fim != a) { + if (go[fim.F][fim.S] == make_pair(fim.F+1, fim.S)) ans.push('U'); + else if (go[fim.F][fim.S] == make_pair(fim.F-1, fim.S)) ans.push('D'); + else if (go[fim.F][fim.S] == make_pair(fim.F, fim.S+1)) ans.push('L'); + else ans.push('R'); + resp++; + fim = go[fim.F][fim.S]; + } + cout << (int)ans.size() << endl; + while(!ans.empty()) { + cout << ans.top(); + ans.pop(); + } + cout << endl; + } + return 0; +} \ No newline at end of file diff --git a/cses/graph/8 - Shortest Routes I.cpp b/cses/graph/8 - Shortest Routes I.cpp new file mode 100644 index 0000000..aa5df9e --- /dev/null +++ b/cses/graph/8 - Shortest Routes I.cpp @@ -0,0 +1,57 @@ +// Shortest Routes I +// +// Problem name: Shortest Routes I +// Problem Link: https://cses.fi/problemset/task/1671 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 100100 +#define INF 1000000000000000LL +#define PB push_back +#define F first +#define S second + +using namespace std; +typedef long long int lli; +typedef pair pii; +const int mod = 1e9+7; + +int n, m; +lli dist[MAXN]; +vector> viz[MAXN]; + +void dijkstra() { + for (int i = 2; i <= n; i++) dist[i] = INF; + dist[1] = 0LL; + priority_queue , vector>, greater>> fila; + fila.push({dist[1], 1}); + while(!fila.empty()) { + int atual = fila.top().S; + lli d = fila.top().F; + fila.pop(); + if (d > dist[atual]) continue; + for (auto v : viz[atual]) { + if (dist[v.S] > d + v.F) { + dist[v.S] = d + v.F; + fila.push({dist[v.S], v.S}); + } + } + } +} + +int main () { _ + int a, b; + lli c; + cin >> n >> m; + for (int i = 0; i < m; i++) { + cin >> a >> b >> c; + viz[a].PB({c, b}); + } + dijkstra(); + for (int i = 1; i <= n; i++) { + cout << dist[i] << " "; + } + cout << endl; + return 0; +} \ No newline at end of file diff --git a/cses/graph/9 - Shortest Routes II.cpp b/cses/graph/9 - Shortest Routes II.cpp new file mode 100644 index 0000000..d74cc33 --- /dev/null +++ b/cses/graph/9 - Shortest Routes II.cpp @@ -0,0 +1,54 @@ +// Shortest Routes II +// +// Problem name: Shortest Routes II +// Problem Link: https://cses.fi/problemset/task/1672 +// Author: Bernardo Archegas (https://codeforces.com/profile/Ber) + +#include +#define _ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); +#define MAXN 505 +#define INF 1000000000000000LL +#define PB push_back +#define F first +#define S second + +using namespace std; +typedef long long int lli; +typedef pair pii; +const int mod = 1e9+7; + +int n, m; +lli dist[MAXN][MAXN]; + +void FW() { + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= n; j++) { + for (int k = 1; k <= n; k++) { + dist[j][k] = min(dist[j][k], dist[j][i] + dist[i][k]); + } + } + } +} + +int main () { _ + int a, b, q; + lli c; + cin >> n >> m >> q; + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= n; j++) { + dist[i][j] = INF; + } + } + for (int i = 0; i < m; i++) { + cin >> a >> b >> c; + dist[a][b] = dist[b][a] = min(dist[a][b], c); + } + for (int i = 1; i <= n; i++) dist[i][i] = 0; + FW(); + for (int i = 0; i < q; i++) { + cin >> a >> b; + if (dist[a][b] == INF) cout << "-1" << endl; + else cout << dist[a][b] << endl; + } + return 0; +} \ No newline at end of file