Загрузка данных
#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;
}