Graph Theory - Directed Graph Condensation

Strongly connected: In a directed graph G, suppose two vertices ab find that there is a way from a to go to b, and there is another way from b to go to a, we call these two vertices (a,b) Strong connectivity.

Strongly connected graph: If in a directed graph G, every two points are strongly connected, we call this graph, a strongly connected graph.

Strongly connected components): In a directed graph G, there is a subgraph, and every 2 points of this subgraph satisfy strong connectivity, and we call this subgraph a strongly connected component.

The shrinking point of a directed graph is to shrink the strongly connected component of the directed graph into a point (the reason is very simple, if I reach any point of the strongly connected component, then the strongly connected component can be accessed by me). There are many uses for the connectivity problem of directed graphs.

For example the following questions:

Given a directed graph with 0 ≤ N ≤ 10 5 points and 0 ≤ M ≤ 10 5 edges,

Output a set of points as small as possible, so that any point can be reached from these points. If there are multiple such sets, output the sets with the smallest lexicographical order after sorting them in ascending order.

The first line contains two integers 1 ≤ n, m ≤ 10 5 , and the
next M lines, where each line contains two integers 1 ≤ u, v ≤ 10 5 means that there is a directed edge from point u to point v.

The data is guaranteed to have no double edges and self-loops.

The first line outputs an integer z, representing the size of the point set as the answer;

The second line outputs z integers, sorted in ascending order, representing the set of points that are the answers.

7 10
4 5
5 1
2 5
6 5
7 2
4 2
1 2
5 3
3 5
3 6
2
4 7

If you don't understand the shrinking point, it is difficult to make it, and there are other methods. Here is an example to solve the problem.

It is actually difficult to find the strongly connected component of the directed graph . This must be understood first. Click to open the link

Let's change the output code, record it in an array and mark each point at the same time, that is, these points are all in a strongly connected component

num records the number of strongly connected components, p is the number of points in the record number of strongly connected components, and unicom indicates that each point belongs to the number of strongly connected components.

Algorithm complexity O(N+E)

This completes our preparatory work. The N points are divided into num strongly connected component blocks.

Asked to verify the connectivity of the directed graph, we also need to use the edge information.

If there is an edge a->b and unicom[a]!=unicom[b], that is, the two points do not belong to the same strongly connected component. So that means that we have reached point a, then all the strongly connected components including point b can be reached.

We mark the strongly connected component unicom[b], this piece does not need to be considered, just consider a.

The S array holds the starting point and the E array holds the end point. e represents the number of edges.

Algorithm complexity O(E)

The total time complexity is O(E+N)

Basically, this connectivity problem is solved, and those strongly connected components that are not marked need to be selected to arrive.

code show as below:

#include<bits/stdc++.h>
using namespace std;

const int maxn=1e5+100;
vector<int> G[maxn],p[maxn],ans;
int low[maxn],dfn[maxn],Stack[maxn],S[maxn],E[maxn],n,e,cnt,Index,num;
int link[maxn],unicom[maxn];
bool vis[maxn];

void tarjan (you and)
{
    low[u]=dfn[u]=++cnt;
    vis [u] = true;
    Stack[++Index]=u;
    for (int i=0;i<G[u].size();i++) {
        int v=G[u][i];
        if (!dfn[v]) {
            Tarjan (v);
            low[u]=min(low[u],low[v]);
        }
        else if (vis [v]) {
            low[u]=min(low[u],dfn[v]);
        }
    }
    if (dfn[u]==low[u]) {
       ++num;
       do {
            p[num].push_back(Stack[Index]);
            unicom[Stack[Index]]=num;
            vis[Stack[Index]]=false;
            Index--;
       }while (u!=Stack[Index+1]);
    }
    return ;
}
intmain()
{
    scanf("%d%d",&n,&e);
    for (int i=1;i<=e;i++) {
        scanf("%d%d",&S[i],&E[i]);
        G[S[i]].push_back(E[i]);
    }
    memset (vis,false,sizeof(vis));
    for (int i=1;i<=n;i++) {
        if (!dfn[i]) tarjan(i);
    }
    for (int i=1;i<=e;i++) {
        if (unicom[S[i]]!=unicom[E[i]])
            link[unicom[E[i]]]=1;
    }
    for (int i=1;i<=num;i++) sort(p[i].begin(),p[i].end());
    for (int i=1;i<=num;i++) {
        if (!link[i]) ans.push_back(p[i][0]);//Just select the first point
    }
    sort(ans.begin(),ans.end());
    printf("%d\n",ans.size());
    for (int i=0;i<ans.size();i++) {
        printf("%d%c",ans[i],(i==ans.size()-1)?'\n':' ');
    }
    return 0;
}










Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325652424&siteId=291194637