Загрузка данных


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

// ============================================================
// ЗАДАЧА 4: количество вершин в компоненте связности (матрица смежности)
// ============================================================
void task4() {
    // Объявляем переменные
    int n, S;          // n — число вершин, S — стартовая вершина
    cin >> n >> S;     // читаем их с ввода
    S--;               // переводим S в 0-индексацию (в условии нумерация с 1)

    // Создаём матрицу смежности размером n x n (макс 100)
    int matrix[100][100];
    // Читаем матрицу
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            cin >> matrix[i][j];
        }
    }

    // Массив посещённых вершин (0 — не посещена, 1 — посещена)
    int visited[100] = {};
    // Счётчик вершин в компоненте
    int count = 0;

    // Рекурсивная функция DFS (лямбда или локальная функция не разрешена в старом C++,
    // поэтому объявляем её внутри как вложенную функцию через struct или используем глобальные переменные.
    // Для простоты сделаем её отдельной функцией внутри, но в C++ нельзя объявлять функции внутри функций.
    // Используем глобальные переменные для этого случая.
    // В целях упрощения перепишем без вложенной функции, а просто объявим глобальную функцию,
    // но для автономности я оформлю через указатели на матрицу и массивы — но проще сделать отдельную функцию,
    // которая принимает матрицу и массивы как параметры.
    // Однако для чистоты кода я создам отдельную функцию dfs4, которая использует глобальные переменные,
    // но мы можем передавать параметры через ссылки. Но проще сделать всё в одной функции task4,
    // используя лямбду (C++11). Так как мы не ограничены, используем лямбду.
    // Для совместимости с C++98 можно использовать отдельную функцию, но мы напишем лямбду.

    // Используем std::function, но проще объявить функцию внутри через auto и recursive lambda.
    // Но мы можем обойтись без рекурсивной лямбды, используя стек или явный вызов.
    // Для простоты и наглядности я создам глобальную функцию dfs4, но для целостности задачи
    // я предпочту использовать отдельную функцию с передачей параметров по ссылке.

    // Так как это объяснительный код, я вынесу DFS в отдельную функцию вне task4,
    // но тогда она будет использовать глобальные переменные. Сделаем проще: используем лямбду с std::function.
    // Но я хочу избежать сложностей. Поэтому я напишу отдельную функцию dfs4, которая принимает
    // матрицу, visited и count по ссылке.

    // Я перепишу задачу 4 так, чтобы функция dfs4 была отдельной, но объявлена внутри task4 не получится,
    // поэтому я объявлю глобальную функцию, которая принимает матрицу, visited и count по ссылке.

    // Для удобства и читаемости я всё-таки использую лямбду (C++11), так как это современный подход.
    // Если препод не разрешает, можно заменить на отдельную функцию.

    // Объявляем лямбду-функцию dfs, которая захватывает все переменные по ссылке
    // и может вызывать себя рекурсивно. Для рекурсивной лямбды нужно использовать std::function,
    // либо передавать её саму в качестве аргумента. Для простоты я сделаю обычную функцию вне.
}

// Но чтобы не усложнять, я лучше вынесу DFS в отдельную глобальную функцию.
// Для задачи 4 я создам глобальные переменные: mat4, vis4, n4, cnt4.
// Это самый простой способ без лямбд.

// Глобальные переменные для задачи 4
int mat4[100][100];
int vis4[100];
int n4;
int cnt4;

void dfs4(int v) {
    vis4[v] = 1;      // помечаем вершину как посещённую
    cnt4++;           // увеличиваем счётчик
    for (int i = 0; i < n4; i++) {
        if (mat4[v][i] == 1 && vis4[i] == 0) {
            dfs4(i);  // рекурсивно обходим соседа
        }
    }
}

void task4() {
    int S;
    cin >> n4 >> S;
    S--;
    for (int i = 0; i < n4; i++) {
        for (int j = 0; j < n4; j++) {
            cin >> mat4[i][j];
        }
    }
    for (int i = 0; i < n4; i++) vis4[i] = 0; // обнуляем массив посещений
    cnt4 = 0;
    dfs4(S);
    cout << cnt4 << endl;
}

// ============================================================
// ЗАДАЧА 5: проверка на двудольность (две группы)
// ============================================================
// Глобальные переменные для задачи 5
vector<int> graph5[100];
int color5[100];
int n5, m5;

bool dfs5(int v, int c) {
    color5[v] = c;                // красим текущую вершину в цвет c
    for (int u : graph5[v]) {     // перебираем соседей
        if (color5[u] == -1) {    // если сосед не окрашен
            if (!dfs5(u, 1 - c)) return false; // запускаем с противоположным цветом
        } else if (color5[u] == c) { // если сосед уже окрашен и цвет совпадает
            return false;         // конфликт, граф не двудольный
        }
    }
    return true;                  // всё хорошо
}

void task5() {
    cin >> n5 >> m5;
    for (int i = 0; i < n5; i++) graph5[i].clear(); // очищаем списки смежности
    for (int i = 0; i < m5; i++) {
        int u, v;
        cin >> u >> v;
        u--; v--;
        graph5[u].push_back(v);
        graph5[v].push_back(u);   // неориентированный граф, добавляем оба направления
    }
    for (int i = 0; i < n5; i++) color5[i] = -1; // инициализируем цвета
    bool bipartite = true;
    for (int i = 0; i < n5; i++) {
        if (color5[i] == -1) {
            if (!dfs5(i, 0)) {
                bipartite = false;
                break;
            }
        }
    }
    cout << (bipartite ? "YES" : "NO") << endl;
}

// ============================================================
// ЗАДАЧА 6: есть ли цикл в ориентированном графе
// ============================================================
int n6, m6;
vector<int> graph6[100000];
int state6[100000]; // 0 - не посещена, 1 - в стеке, 2 - обработана

bool dfs6(int v) {
    state6[v] = 1;                // помечаем, что вошли в вершину
    for (int u : graph6[v]) {
        if (state6[u] == 0) {     // если не посещена
            if (dfs6(u)) return true;
        } else if (state6[u] == 1) { // если в стеке, значит, нашли цикл
            return true;
        }
    }
    state6[v] = 2;                // выходим, помечаем обработанной
    return false;
}

void task6() {
    cin >> n6 >> m6;
    for (int i = 0; i < n6; i++) graph6[i].clear();
    for (int i = 0; i < m6; i++) {
        int u, v;
        cin >> u >> v;
        u--; v--;
        graph6[u].push_back(v);   // ориентированное ребро
    }
    for (int i = 0; i < n6; i++) state6[i] = 0;
    bool hasCycle = false;
    for (int i = 0; i < n6; i++) {
        if (state6[i] == 0) {
            if (dfs6(i)) {
                hasCycle = true;
                break;
            }
        }
    }
    cout << (hasCycle ? 1 : 0) << endl;
}

// ============================================================
// ГЛАВНАЯ ФУНКЦИЯ
// ============================================================
int main() {
    // Раскомментируйте нужную задачу:
    // task4();   // компонента связности
    // task5();   // двудольность
    // task6();   // цикл в ориентированном графе
    return 0;
}