Компоненты сильной связности. Алгоритм Косараю-Шарира: различия между версиями

Материал из Олимпиадное программирование в УлГТУ
Перейти к навигации Перейти к поиску
Нет описания правки
Нет описания правки
 
Строка 11: Строка 11:
  struct Graph {
  struct Graph {
     vector<vector<int>> graph, graphR;
     vector<vector<int>> graph, graphR;
     vector<int> visited, order;
     vector<int> visited, order, sccOf;
   
   
     Graph(int vertexCount) :
     Graph(int vertexCount) :
Строка 30: Строка 30:
   
   
     void dfs2(int v, int component) {
     void dfs2(int v, int component) {
         visited[v] = component;
         sccOf[v] = component;
         for (int to : graphR[v])
         for (int to : graphR[v])
             if (!visited[to])
             if (sccOf[to] == -1)
                 dfs2(to, component);
                 dfs2(to, component);
     }
     }
Строка 43: Строка 43:
         reverse(order.begin(), order.end());
         reverse(order.begin(), order.end());
   
   
         visited.assign(graph.size(), 0);
         sccOf.assign(graph.size(), -1);
         int sccCount = 0;
         int sccCount = 0;
         for (int v : order)
         for (int v : order)
             if (!visited[v])
             if (sccOf[v] == -1)
                 dfs2(v, ++sccCount);
                 dfs2(v, sccCount++);
   
   
         return visited;
         return sccOf;
     }
     }
  };
  };
Строка 56: Строка 56:
  struct Graph {
  struct Graph {
     vector<vector<int>> graph, graphR;
     vector<vector<int>> graph, graphR;
     vector<int> visited, order;
     vector<int> visited, order, sccOf;
   
   
     Graph(int vertexCount) :
     Graph(int vertexCount) :
Строка 75: Строка 75:
   
   
     void dfs2(int v, int component) {
     void dfs2(int v, int component) {
         visited[v] = component;
         sccOf[v] = component;
         for (int to : graphR[v])
         for (int to : graphR[v])
             if (!visited[to])
             if (sccOf[to] == -1)
                 dfs2(to, component);
                 dfs2(to, component);
     }
     }
Строка 88: Строка 88:
         reverse(order.begin(), order.end());
         reverse(order.begin(), order.end());
   
   
         visited.assign(graph.size(), 0);
         sccOf.assign(graph.size(), -1);
         int sccCount = 0;
         int sccCount = 0;
         for (int v : order)
         for (int v : order)
             if (!visited[v])
             if (sccOf[v] == -1)
                 dfs2(v, ++sccCount);
                 dfs2(v, sccCount++);
   
   
         vector<set<int>> graphC(sccCount);
         vector<set<int>> graphC(sccCount);
         for (int v = 0; v < graph.size(); v++)
         for (int v = 0; v < graph.size(); v++)
             for (int to : graph[v])
             for (int to : graph[v])
                 if (visited[v] != visited[to])
                 if (sccOf[v] != sccOf[to])
                     graphC[visited[v]].insert(visited[to]);
                     graphC[sccOf[v]].insert(sccOf[to]);
   
   
         return graphC;
         return graphC;

Текущая версия от 15:33, 30 июня 2023

TLDR

Код

  • Упорядочиваем вершины по убыванию времени выхода (как при топологической сортировке).
  • Транспонируем граф.
  • Обходим вершины транспонированного графа в порядке убывания времени выхода ("порядке топологической сортировки").
struct Graph {
    vector<vector<int>> graph, graphR;
    vector<int> visited, order, sccOf;

    Graph(int vertexCount) :
        graph(vertexCount), graphR(vertexCount) {}

    void addEdge(int a, int b) {
        graph[a].push_back(b);
        graphR[b].push_back(a);
    }

    void dfs1(int v) {
        visited[v] = 1;
        for (int to : graph[v])
            if (!visited[to])
                dfs1(to);
        order.push_back(v);
    }

    void dfs2(int v, int component) {
        sccOf[v] = component;
        for (int to : graphR[v])
            if (sccOf[to] == -1)
                dfs2(to, component);
    }

    vector<int> getScc() {
        visited.assign(graph.size(), 0);
        for (int v = 0; v < graph.size(); v++)
            if (!visited[v])
                dfs1(v);
        reverse(order.begin(), order.end());

        sccOf.assign(graph.size(), -1);
        int sccCount = 0;
        for (int v : order)
            if (sccOf[v] == -1)
                dfs2(v, sccCount++);

        return sccOf;
    }
};
struct Graph {
    vector<vector<int>> graph, graphR;
    vector<int> visited, order, sccOf;

    Graph(int vertexCount) :
        graph(vertexCount), graphR(vertexCount) {}

    void addEdge(int a, int b) {
        graph[a].push_back(b);
        graphR[b].push_back(a);
    }

    void dfs1(int v) {
        visited[v] = 1;
        for (int to : graph[v])
            if (!visited[to])
                dfs1(to);
        order.push_back(v);
    }

    void dfs2(int v, int component) {
        sccOf[v] = component;
        for (int to : graphR[v])
            if (sccOf[to] == -1)
                dfs2(to, component);
    }

    vector<set<int>> condense() {
        visited.assign(graph.size(), 0);
        for (int v = 0; v < graph.size(); v++)
            if (!visited[v])
                dfs1(v);
        reverse(order.begin(), order.end());

        sccOf.assign(graph.size(), -1);
        int sccCount = 0;
        for (int v : order)
            if (sccOf[v] == -1)
                dfs2(v, sccCount++);

        vector<set<int>> graphC(sccCount);
        for (int v = 0; v < graph.size(); v++)
            for (int to : graph[v])
                if (sccOf[v] != sccOf[to])
                    graphC[sccOf[v]].insert(sccOf[to]);

        return graphC;
    }
};

Ссылки

Теория:

Демонстрация:

Код:

Задачи: