January 2019 Icy Perimeter

Given a n x n grid full of # (contained) or . (empty), find the largest component of #s with the largest area, and the lowest perimeter if there’s a tie. Print it’s area followed by the perimeter.

I tried debugging this code on the test cases, looking at the solution, but I couldn’t find any clear bugs. My code is getting a TLE on test 10, AC on 1-3, and MLE/Runtime Error on the remaining ones.

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

class Point {
    public:
        int x, y;

        Point(int x, int y) {
            this->x = x;
            this->y = y;
        }

        int operator == (const Point &other) const {
            return (x == other.x) && (y == other.y);
        }
};

vector<vector<bool>> visited_nodes(1000, vector<bool>(1000, false));

pair<int, int> flood_fill(Point point, int area, int perimeter, vector<vector<char>> graph) {
    if ((point.x < 0) || (point.x >= graph.size()) || (point.y < 0) || (point.y >= graph.size())) {
        perimeter += 1;
    }

    else if (visited_nodes.at(point.y).at(point.x)) {
        return make_pair(area, perimeter);
    }
    
    else if (graph.at(point.y).at(point.x) == '.') {
        perimeter += 1;
    }

    else {
        area += 1;
        visited_nodes.at(point.y).at(point.x) = true;
        
        for (int x_change = -1; x_change <= 1; x_change++) {
            for (int y_change = -1; y_change <= 1; y_change++) {
                if (abs(x_change) == abs(y_change)) {
                    continue;
                }

                pair<int, int> update = flood_fill({point.x + x_change, point.y + y_change}, area, perimeter, graph);
                area = update.first;
                perimeter = update.second;
            }
        }
    }

    return make_pair(area, perimeter);
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    freopen("perimeter.in", "r", stdin);
    freopen("perimeter.out", "w", stdout);

    int size;
    cin >> size;

    vector<vector<char>> graph(size, vector<char>(size));

    for (int row = 0; row < size; row++) {
        string input;
        cin >> input;

        for (int column = 0; column < size; column++) {
            graph.at(row).at(column) = input.at(column);
        }
    }

    int maximum_area = -1;
    int perimeter = -1;

    for (int row = 0; row < size; row++) {
        for (int column = 0; column < size; column++) {
            Point point(column, row);

            if ((visited_nodes.at(point.y).at(point.x) > 0) || (graph.at(row).at(column) == '.')) {
                continue;
            }

            pair<int, int> update = flood_fill(point, 0, 0, graph);

            if (update.first == maximum_area) {
                perimeter = min(perimeter, update.second);
            }

            if (update.first > maximum_area) {
                maximum_area = update.first;
                perimeter = update.second;
            }
        }
    }

    cout << maximum_area << ' ' << perimeter << "\n";
    return 0;
}