AtCoder ABC 447 Contest Solutions

Problem D - Take ABC 2

An efficient approach involves processing the string from the end to identify and count valid "ABC" sequences.


#include <vector>
#include <string>
#include <iostream>
using namespace std;

void processString() {
    string input;
    cin >> input;
    vector<int> posA, posB, posC;
    
    for (int idx = 0; idx < input.length(); idx++) {
        if (input[idx] == 'A') posA.push_back(idx);
        else if (input[idx] == 'B') posB.push_back(idx);
        else if (input[idx] == 'C') posC.push_back(idx);
    }
    
    int result = 0;
    while (!posC.empty()) {
        int cPos = posC.back();
        posC.pop_back();
        
        while (!posB.empty() && posB.back() > cPos)
            posB.pop_back();
        if (posB.empty()) break;
        
        int bPos = posB.back();
        posB.pop_back();
        
        while (!posA.empty() && posA.back() > bPos)
            posA.pop_back();
        if (posA.empty()) break;
        
        posA.pop_back();
        result++;
    }
    cout << result;
}

Problem E - Divide Graph

This solution uses a union-find data structure to determine the minimum edges needed to split the graph into two connected components.


#include <vector>
#include <algorithm>
using namespace std;

const int MAX_N = 100005;
const int MOD = 998244353;

struct Edge {
    int from, to, weight;
};

int parent[MAX_N];
long long power[MAX_N];

int findRoot(int x) {
    if (x == parent[x]) return x;
    return parent[x] = findRoot(parent[x]);
}

bool compareEdges(Edge x, Edge y) {
    return x.weight > y.weight;
}

void solveGraph() {
    int n, m;
    cin >> n >> m;
    
    power[0] = 1;
    for (int i = 1; i <= m; i++)
        power[i] = (power[i-1] * 2) % MOD;
    
    vector<Edge> edges(m+1);
    for (int i = 1; i <= n; i++)
        parent[i] = i;
    
    for (int i = 1; i <= m; i++) {
        int u, v;
        cin >> u >> v;
        edges[i] = {u, v, i};
    }
    
    sort(edges.begin() + 1, edges.end(), compareEdges);
    
    int components = n;
    long long answer = 0;
    
    for (int i = 1; i <= m; i++) {
        int rootU = findRoot(edges[i].from);
        int rootV = findRoot(edges[i].to);
        
        if (rootU != rootV) {
            if (components > 2) {
                parent[rootU] = rootV;
                components--;
            } else {
                answer = (answer + power[edges[i].weight]) % MOD;
            }
        }
    }
    cout << answer;
}

Problem F - Centipede Graph

A tree dynamic programming solution that comuptes the maximum centipeed path length in a tree structure.


#include <vector>
#include <algorithm>
using namespace std;

const int MAX_N = 200005;
vector<int> tree[MAX_N];
int dp[MAX_N][2], children[MAX_N];

void countChildren(int node, int parent) {
    for (int neighbor : tree[node]) {
        if (neighbor == parent) continue;
        children[node]++;
        countChildren(neighbor, node);
    }
}

void computeDP(int node, int parent) {
    int firstMax = 0, secondMax = 0;
    
    if (children[node] >= 2) {
        dp[node][1] = 1;
        dp[node][0] = 1;
    }
    if (children[node] >= 1 && parent != 0)
        dp[node][0] = 1;
    
    for (int neighbor : tree[node]) {
        if (neighbor == parent) continue;
        computeDP(neighbor, node);
        
        if (dp[neighbor][1] >= firstMax) {
            secondMax = firstMax;
            firstMax = dp[neighbor][1];
        } else if (dp[neighbor][1] > secondMax) {
            secondMax = dp[neighbor][1];
        }
        dp[node][0] = max(dp[node][0], dp[neighbor][0]);
    }
    
    if (node == 1) {
        if (children[node] >= 4)
            dp[node][0] = max(dp[node][0], firstMax + secondMax + 1);
        if (children[node] == 3)
            dp[node][0] = max(dp[node][0], firstMax + 1);
    } else {
        if (children[node] >= 3)
            dp[node][0] = max(dp[node][0], firstMax + secondMax + 1);
        if (children[node] == 2)
            dp[node][0] = max(dp[node][0], firstMax + 1);
    }
    
    if (children[node] >= 3)
        dp[node][1] = firstMax + 1;
}

void solveCentipede() {
    int n;
    cin >> n;
    
    for (int i = 1; i < n; i++) {
        int u, v;
        cin >> u >> v;
        tree[u].push_back(v);
        tree[v].push_back(u);
    }
    
    countChildren(1, 0);
    computeDP(1, 0);
    cout << dp[1][0] << endl;
}

Tags: AtCoder competitive-programming Union-Find dynamic-programming tree-algorithms

Posted on Sat, 11 Jul 2026 16:17:57 +0000 by Sa177ir