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

Материал из Олимпиадное программирование в УлГТУ
Перейти к навигации Перейти к поиску
Нет описания правки
Нет описания правки
Строка 7: Строка 7:
* Обходим вершины транспонированного графа в порядке убывания времени выхода ("порядке топологической сортировки").
* Обходим вершины транспонированного графа в порядке убывания времени выхода ("порядке топологической сортировки").


  vector<vector<int>> graph(vertexCount), graphR(vertexCount);
{|width=100%
vector<int> visited(vertexCount);
|width=50%|
vector<int> order;
  struct Graph {
    vector<vector<int>> graph, graphR;
    vector<int> visited, order;
   
   
void dfs1(int v) {
    Graph(int vertexCount) :
    visited[v] = 1;
         graph(vertexCount), graphR(vertexCount) {}
    for (int to : graph[v])
         if (!visited[to])
            dfs1(to);
    order.push_back(v);
}
   
   
void dfs2(int v, int component) {
    void addEdge(int a, int b) {
    visited[v] = component;
        graph[a].push_back(b);
    for (int to : graphR[v])
         graphR[b].push_back(a);
         if (!visited[to])
    }
            dfs2(to, component);
}
   
   
for (int v = 0; v < vertexCount; v++)
    void dfs1(int v) {
    if (!visited[v])
        visited[v] = 1;
        dfs1(v);
        for (int to : graph[v])
reverse(order.begin(), order.end());
            if (!visited[to])
                dfs1(to);
        order.push_back(v);
    }
   
   
fill(visited.begin(), visited.end(), 0);
    void dfs2(int v, int component) {
        visited[v] = component;
        for (int to : graphR[v])
            if (!visited[to])
                dfs2(to, component);
    }
   
   
  int componentCount = 0;
    vector<int> getScc() {
for (int v : order)
        visited.assign(graph.size(), 0);
    if (!visited[v])
        for (int v = 0; v < graph.size(); v++)
        dfs2(v, ++componentCount);
            if (!visited[v])
 
                dfs1(v);
Построение конденсации:
        reverse(order.begin(), order.end());
   
        visited.assign(graph.size(), 0);
        int sccCount = 0;
        for (int v : order)
            if (!visited[v])
                dfs2(v, ++sccCount);
        return visited;
    }
};
|width=50%|


  struct Graph {
  struct Graph {
     int vertexCount, sccCount;
     vector<vector<int>> graph, graphR;
    map<int, set<int>> g, gr, gc;
     vector<int> visited, order;
     set<int> visited;
    vector<int> order;
    map<int, int> sccIndexOf, sccSize;
   
   
     Graph(int vertexCount) : vertexCount(vertexCount), sccCount(0) {}
     Graph(int vertexCount) :
        graph(vertexCount), graphR(vertexCount) {}
   
   
     void addEdge(int a, int b) {
     void addEdge(int a, int b) {
         g[a].insert(b);
         graph[a].push_back(b);
         gr[b].insert(a);
         graphR[b].push_back(a);
     }
     }
   
   
     void dfs1(int v) {
     void dfs1(int v) {
         visited.insert(v);
         visited[v] = 1;
         for (int to : g[v])
         for (int to : graph[v])
             if (!visited.count(to))
             if (!visited[to])
                 dfs1(to);
                 dfs1(to);
         order.push_back(v);
         order.push_back(v);
Строка 63: Строка 75:
   
   
     void dfs2(int v, int component) {
     void dfs2(int v, int component) {
         visited.insert(v);
         visited[v] = component;
        sccIndexOf[v] = component;
         for (int to : graphR[v])
        sccSize[component]++;
             if (!visited[to])
         for (int to : gr[v]) {
             if (!visited.count(to))
                 dfs2(to, component);
                 dfs2(to, component);
        }
     }
     }
   
   
     void condense() {
     vector<set<int>> condense() {
         for (int v = 0; v < vertexCount; v++)
        visited.assign(graph.size(), 0);
             if (!visited.count(v))
         for (int v = 0; v < graph.size(); v++)
             if (!visited[v])
                 dfs1(v);
                 dfs1(v);
         reverse(order.begin(), order.end());
         reverse(order.begin(), order.end());
   
   
         visited.clear();
         visited.assign(graph.size(), 0);
        int sccCount = 0;
         for (int v : order)
         for (int v : order)
             if (!visited.count(v))
             if (!visited[v])
                 dfs2(v, sccCount++);
                 dfs2(v, ++sccCount);
        vector<set<int>> graphC(sccCount);
        for (int v = 0; v < graph.size(); v++)
            for (int to : graph[v])
                if (visited[v] != visited[to])
                    graphC[visited[v]].insert(visited[to]);
   
   
         for (int v = 0; v < vertexCount; v++)
         return graphC;
            for (int to : g[v])
                if (sccIndexOf[v] != sccIndexOf[to])
                    gc[sccIndexOf[v]].insert(sccIndexOf[to]);
     }
     }
  };
  };
|}


== Ссылки ==
== Ссылки ==

Версия от 15:21, 30 июня 2023

TLDR

Код

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

    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) {
        visited[v] = component;
        for (int to : graphR[v])
            if (!visited[to])
                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());

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

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

    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) {
        visited[v] = component;
        for (int to : graphR[v])
            if (!visited[to])
                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());

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

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

        return graphC;
    }
};

Ссылки

Теория:

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

Код:

Задачи: