Skip to content

USACO 2018 US Open Contest Silver Division - Multiplayer Moo#

Problem link: here

Solution Author: Stefan Dascalescu

Problem Solution#

For one-cow, just find connected components. For two-cow, always keep a lower-bound for the greatest component. Start from the two largest groups, then continue to pair smaller and smaller groups until the overall sum of positions is less than the lower-bound of the greatest component.

Source code#

The source code in C++ can be seen below.

#include <bits/stdc++.h>
using namespace std;

#define fi first
#define se second

const int MOD = 1e9+7;
const int INF = (1<<30);
const int ALP = 26;
const long long LL_INF = (1LL<<60);

const int MAX_N = 250;
const int MAX_A = 1e6;

int N;
int A[MAX_N + 5][MAX_N + 5];
int maxComp[MAX_A + 5];
int total[MAX_A + 5];
bool seen[MAX_N + 5][MAX_N + 5];
int maxComp2;
int cnt;

bool cmp(int X, int Y) {
    return total[X] > total[Y];
}

void DFS(int x, int y) {
    if (seen[x][y]) return;
    seen[x][y] = true;
    cnt++;
    maxComp[A[x][y]] = max(maxComp[A[x][y]], cnt);
    total[A[x][y]]++;
    for (int x2 = x - 1; x2 <= x + 1; x2++) {
        for (int y2 = y - 1; y2 <= y + 1; y2++) {
            if (x2 != x && y2 != y) continue;
            if (x2 == x && y2 == y) continue;
            if (x2 < 1 || x2 > N) continue;
            if (y2 < 1 || y2 > N) continue;
            if (A[x][y] != A[x2][y2]) continue;
            DFS(x2, y2);
        }
    }
}

void DFS2(int x, int y, int t1, int t2) {
    if (seen[x][y]) return;
    seen[x][y] = true;
    cnt++;
    maxComp2 = max(maxComp2, cnt);
    for (int x2 = x - 1; x2 <= x + 1; x2++) {
        for (int y2 = y - 1; y2 <= y + 1; y2++) {
            if (x2 != x && y2 != y) continue;
            if (x2 == x && y2 == y) continue;
            if (x2 < 1 || x2 > N) continue;
            if (y2 < 1 || y2 > N) continue;
            if (A[x2][y2] != t1 && A[x2][y2] != t2) continue;
            DFS2(x2, y2, t1, t2);
        }
    }
}

int main() {
    freopen("multimoo.in", "r", stdin);
    freopen("multimoo.out", "w", stdout);
    cin >> N;
    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= N; j++) {
            cin >> A[i][j];
        }
    }
    // One Cow
    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= N; j++) {
            if (seen[i][j]) continue;
            cnt = 0;
            DFS(i, j);
        }
    }
    int ans1 = 0;
    vector<int> vals;
    for (int i = 0; i <= MAX_A; i++) {
        if (!maxComp[i]) continue;
        ans1 = max(ans1, maxComp[i]);
        vals.push_back(i);
    }
    cout << ans1 << "\n";
    // Two Cows
    sort(vals.begin(), vals.end(), cmp);
    int M = (int)vals.size();
    int L = 0;
    int R = 1;
    int ans2 = 0;
    while (L < M && R < M) {
        if (total[vals[L]] + total[vals[R]] <= ans2) {
            L++;
            R = L + 1;
            continue;
        }
        for (int i = 1; i <= N; i++) {
            for (int j = 1; j <= N; j++) {
                seen[i][j] = false;
            }
        }
        maxComp2 = 0;
        int t1 = vals[L];
        int t2 = vals[R];
        for (int i = 1; i <= N; i++) {
            for (int j = 1; j <= N; j++) {
                if (A[i][j] != t1 &&
                    A[i][j] != t2) continue;
                if (seen[i][j]) continue;
                cnt = 0;
                DFS2(i, j, t1, t2);
            }
        }
        ans2 = max(ans2, maxComp2);
        R++;
    }
    cout << ans2 << "\n";
}