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


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

// ============================================================
// ЗАДАЧА 4: количество вершин в компоненте связности
// (используем матрицу смежности, n ≤ 100)
// ============================================================

// Рекурсивная функция DFS для задачи 4.
// Принимает:
//   v - текущая вершина,
//   matrix - матрица смежности (двумерный массив),
//   n - количество вершин,
//   visited - массив посещений (передаётся по ссылке, чтобы менять),
//   count - счётчик (передаётся по ссылке, чтобы менять).
void dfs4(int v, int matrix[100][100], int n, bool visited[], int &count) {
    visited[v] = true;      // помечаем вершину как посещённую
    count++;                // увеличиваем счётчик (мы нашли новую вершину в компоненте)

    // Перебираем все вершины i от 0 до n-1
    for (int i = 0; i < n; i++) {
        // Если есть ребро из v в i (matrix[v][i] == 1) и i ещё не посещена
        if (matrix[v][i] == 1 && !visited[i]) {
            dfs4(i, matrix, n, visited, count); // рекурсивно обходим i
        }
    }
}

void task4() {
    int n, S;
    cin >> n >> S;
    S--; // переводим в 0-индексацию

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

    bool visited[100] = {false}; // массив посещений, инициализируем false
    int count = 0;               // счётчик вершин в компоненте

    dfs4(S, matrix, n, visited, count); // запускаем DFS из S

    cout << count << endl;
}

// ============================================================
// ЗАДАЧА 5: проверка на двудольность (две группы)
// Используем список смежности (векторы), n ≤ 100
// ============================================================

// Рекурсивная функция DFS для раскраски.
// Возвращает true, если удалось раскрасить подграф без конфликтов.
// Параметры:
//   v - текущая вершина,
//   color - цвет, который присваиваем v (0 или 1),
//   graph - список смежности,
//   colors - массив цветов (-1, 0, 1) – передаётся по ссылке.
bool dfs5(int v, int color, const vector<int> graph[], int colors[]) {
    colors[v] = color; // красим вершину

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

void task5() {
    int n, m;
    cin >> n >> m;

    vector<int> graph[100]; // список смежности (макс 100 вершин)
    for (int i = 0; i < m; i++) {
        int u, v;
        cin >> u >> v;
        u--; v--;
        graph[u].push_back(v);
        graph[v].push_back(u); // неориентированный граф – добавляем оба направления
    }

    int colors[100]; // массив цветов: -1 – не окрашена, 0 или 1
    for (int i = 0; i < n; i++) colors[i] = -1; // инициализация

    bool bipartite = true;
    // Запускаем DFS из каждой вершины, чтобы обработать все компоненты связности
    for (int i = 0; i < n; i++) {
        if (colors[i] == -1) { // если вершина не окрашена
            if (!dfs5(i, 0, graph, colors)) { // начинаем с цвета 0
                bipartite = false;
                break;
            }
        }
    }

    cout << (bipartite ? "YES" : "NO") << endl;
}

// ============================================================
// ЗАДАЧА 6: есть ли цикл в ориентированном графе
// Используем список смежности (векторы), n ≤ 100000
// ============================================================

// DFS с тремя состояниями.
// Возвращает true, если найден цикл.
// Параметры:
//   v - текущая вершина,
//   graph - список смежности,
//   state - массив состояний (0,1,2) – передаётся по ссылке.
bool dfs6(int v, const vector<int> graph[], int state[]) {
    state[v] = 1; // помечаем, что вошли в вершину (в стеке)

    for (int u : graph[v]) {
        if (state[u] == 0) { // если сосед не посещён
            if (dfs6(u, graph, state)) {
                return true; // если рекурсия нашла цикл – передаём дальше
            }
        } else if (state[u] == 1) { // если сосед уже в стеке – нашли цикл
            return true;
        }
        // state[u] == 2 – обработана, ничего не делаем
    }

    state[v] = 2; // выходим, помечаем как обработанную
    return false; // цикл не найден
}

void task6() {
    int n, m;
    cin >> n >> m;

    vector<int> graph[100000]; // список смежности для до 100000 вершин
    for (int i = 0; i < m; i++) {
        int u, v;
        cin >> u >> v;
        u--; v--;
        graph[u].push_back(v); // ориентированное ребро u -> v
    }

    int state[100000]; // состояния: 0 – не посещена, 1 – в стеке, 2 – обработана
    for (int i = 0; i < n; i++) state[i] = 0; // инициализация

    bool hasCycle = false;
    // Запускаем DFS из каждой вершины, если она не посещена
    for (int i = 0; i < n; i++) {
        if (state[i] == 0) {
            if (dfs6(i, graph, state)) {
                hasCycle = true;
                break;
            }
        }
    }

    cout << (hasCycle ? 1 : 0) << endl;
}

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