π§© AtCoder Beginner Contest 394
π§© AtCoder Beginner Contest 394
# Info & Summary
- Date:
2025-02-22
- Completion Status: A β / B β / C β / D β / E β / F β / G β
- Problem Type:
Problem | Type(s) | Data Structure / Algo | π₯ Key Insight / Mark |
---|---|---|---|
E | Shortest Path | BFS | π§ π₯ |
F | Tree DP | Tree DP/DFS | π₯ |
Details
Emoji | Label | Meaning |
---|---|---|
β | Important | Problem is strategically useful or has reusable patterns |
π₯ | Must master | Classic problem or technique that appears often and is worth mastering |
β οΈ | Reattempt | You attempted but failed; worth reviewing and solving again |
π§ | New to me | Introduced a new idea, technique, or pattern you hadnβt seen before |
π οΈ | Template | You built or improved a code template from solving this problem |
π | Too hard now | Beyond current ability to understand/solve; revisit after more practice |
π A - 22222

#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
string s;
cin >> s;
string ans = "";
for (auto c : s)
{
if (c == '2')
{
ans += c;
}
}
cout << ans << endl;
return 0;
}
π B - cat

#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
vector<string> s(n);
for (int i = 0; i < n; i++)
{
cin >> s[i];
}
sort(s.begin(), s.end(), [&](string i, string j){
return i.size() < j.size();
});
string ans = "";
for (auto a : s)
{
ans += a;
}
cout << ans << endl;
return 0;
}
π C - Debug

#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
string s;
cin >> s;
int n = s.size();
for (int i = 0; i < n - 1; i++)
{
if (s[i] == 'W' && s[i + 1] == 'A')
{
s[i] = 'A';
s[i + 1] = 'C';
int l = i;
while (l - 1 >= 0 && s[l - 1] == 'W')
{
s[l - 1] = 'A';
s[l] = 'C';
l--;
}
}
}
cout << s << endl;
return 0;
}
π D - Colorful Bracket Sequence

#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
string s;
cin >> s;
stack<char> st;
for (auto c : s)
{
if (!st.empty() && ((st.top() == '(' && c == ')') || (st.top() == '[' && c == ']') || (st.top() == '<' && c == '>')))
{
st.pop();
} else {
st.push(c);
}
}
cout << (st.empty() ? "Yes" : "No") << endl;
return 0;
}
π E - Palindromic Shortest Path

Tips
For a lowercase English letter and a palindrome , the string obtained by concatenating , , and in this order forms a palindrome
Conversely, a string of length at least two is a palindrome if and only if the first and the last characters are the same, and the string obtained by removing the first and last characters still forms a palindrome
Let be a graph with vertices . We will decide the edges so that vertex corresponds to a path from vertex to vertex in the graph given in the problem statement
For convenience, add another vertex to for it to have . Then the answer to the original problem for an integer pair is the length of a shortest path from to in the graph with edges added as follows:
- An edge from to of weight for each
- An edge from to for each with
- An edge from to of weight for each with , ,
- means a new path:
- correspond to adding the same character at the beginning and the end of a palindrome to obtain a new palindrome with the length increased by two
has vertices, each of degree , so it has edges, allowing -time BFS
to find the answer
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
vector<vector<char>> c(n, vector<char>(n));
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
cin >> c[i][j];
}
}
vector<vector<int>> dist(n, vector<int>(n, 1e9));
queue<pair<int, int>> q;
for (int i = 0; i < n; i++)
{
q.push({i, i});
dist[i][i] = 0;
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (i == j || c[i][j] == '-')
{
continue;
}
q.push({i, j});
dist[i][j] = 1;
}
}
while (!q.empty())
{
auto p = q.front();
q.pop();
int i = p.first, j = p.second;
for (int k = 0; k < n; k++)
{
for (int l = 0; l < n; l++)
{
// There is no edge from k->i or j->l
if (c[k][i] == '-' || c[j][l] == '-')
{
continue;
}
// The characters at both ends of the edges do not match
if (c[k][i] != c[j][l])
{
continue;
}
// adding characters from both sides of the path
if (dist[i][j] + 2 <= dist[k][l])
{
dist[k][l] = dist[i][j] + 2;
q.push({k, l});
}
}
}
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
cout << (dist[i][j] == 1e9 ? -1 : dist[i][j]) << " \n"[j == n - 1];
}
}
return 0;
}
π F - Alkane

Note
Since the subgraph of the tree must form another tree, once the vertex subset is fixed, the edge set is unique (if any). Thus we will identify a subgraph that forms a tree and its vertex set (that yields a tree by choosing edges appropriately)
Tips
A graph is an alkane if and only if the graph has or more vertices and is a general alkane, so it is sufficient to find the maximum vertices in a general alkane
We call a graph (with one or more vertices) general alkane if and only if:
- the graph is an undirected tree
- every vertex has a degree or
Tips
For a non-root vertex , let be the maximum number of vertices in a subtree consisting of ancestors of (possibly including itself) such that adding results in a general alkane
Suppose that we have already evaluated all the ancestors of (except for )
How can we compute :
- Case 1: if 's degree is
- only 's parent is adjacent to , so the number of vertices is
- then the maximum number of vertices is , where is the vertex adjacent to
- Case 2: if 's degree is
- then the vertices adjacent to is 's parent and three children of , so must have at least children
- if i does, we can pick children together with, for each children, a vertex set to which adding the parent of the child forms a general alkane
- by maximizing the number of vertices in those vertex set by picking three children with largest values of , we can obtain a conforming vertex set with vertices
A more understandable version
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
vector<vector<int>> adj(n, vector<int>());
for (int i = 0; i < n - 1; i++)
{
int u, v;
cin >> u >> v;
u--;
v--;
adj[u].push_back(v);
adj[v].push_back(u);
}
int ans = -1;
vector<vector<int>> dp(n, vector<int>(5, -1e8));
auto dfs = [&](auto &&self, int u, int p) -> void
{
for (auto v : adj[u])
{
if (v == p)
{
continue;
}
self(self, v, u);
}
dp[u][0] = 1;
vector<int> child;
for (auto v : adj[u])
{
if (v == p)
{
continue;
}
ans = max(ans, dp[v][3] + 1);
child.push_back(dp[v][3]);
}
sort(child.rbegin(), child.rend());
int k = child.size();
if (k >= 4)
{
ans = max(ans, child[0] + child[1] + child[2] + child[3] + 1);
ans = max(ans, child[0] + child[1] + child[2] + 2);
ans = max(ans, child[0] + child[1] + 3);
ans = max(ans, child[0] + 4);
ans = max(ans, 5);
}
if (k >= 1)
{
ans = max(ans, child[0] + 1);
}
if (k >= 3)
{
dp[u][3] = max(dp[u][3], child[0] + child[1] + child[2] + 1);
dp[u][3] = max(dp[u][3], child[0] + child[1] + 2);
dp[u][3] = max(dp[u][3], child[0] + 3);
dp[u][3] = max(dp[u][3], 4);
}
};
dfs(dfs, 0, -1);
cout << ans << endl;
return 0;
}
// Better version
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
vector<vector<int>> adj(n, vector<int>());
for (int i = 0; i < n - 1; i++)
{
int u, v;
cin >> u >> v;
u--;
v--;
adj[u].push_back(v);
adj[v].push_back(u);
}
int ans = -1;
auto dfs = [&](auto &&self, int u, int p) -> int
{
vector<int> child;
for (auto v : adj[u])
{
if (v == p)
{
continue;
}
child.push_back(self(self, v, u));
}
sort(child.rbegin(), child.rend());
int k = child.size();
if (k >= 1 && child[0] > 1)
{
ans = max(ans, child[0] + 1);
}
if (k >= 4)
{
ans = max(ans, child[0] + child[1] + child[2] + child[3] + 1);
}
return k < 3 ? 1 : child[0] + child[1] + child[2] + 1;
};
dfs(dfs, 0, -1);
cout << ans << endl;
return 0;
}
π G - Dense Buildings

Warning
Hard Problems to Tackle Later
// TODO