Algorithm Series note 6 (algorithm one for graphs-search, topological sort, and strongly connected branch)

Source: Internet
Author: User

Simple concept: for Figure G (v,e), there are usually two kinds of stored data structure, one is the adjacency matrix, the storage space required is O (v^2), and the second is the adjacency table, the required storage space is O (v+e). adjacency table notation has a strong adaptability, but there are potential deficiencies, when you want to quickly determine whether the edge (u,v) in the graph, only in the adjacency table of vertex u search for V, there is no faster method, the adjacency matrix can be used at this time, but to occupy more storage space as a cost; Moreover, when the graph is not weighted, There is also an advantage to using adjacency matrix storage: When storing each element of the adjacency matrix, you can use only one binary instead of a single word space.

A search algorithm for graphs

Search for an icon to access all vertices in an orderly way along the edges of the graph, with two main search algorithms, breadth-first traversal (BFS, also known as width traversal), and depth-first traversal (DFS).

Breadth First (BFS)

From the source point s to the breadth-first traversal of the graph, the resulting path is the shortest path from the source point S to the other points, and a breadth-first tree is generated. Breadth-first traversal requires a queue, FIFO.

The code is as follows:

Breadth traversal diagram void Graph::bfs (int s) {queue<int> Q;q.push (s); Visited[s] = 1;while (!q.empty ()) {int u = q.front (); Q.pop (); cout << u << ""; Gnode *p = Edges[u].next;while (P! = NULL) {if (!visited[p->val]) {    //is not accessed, it is added to the queue and is marked for access to Q.push (P->val); Visited[p->val] = 1;} p = P->next;}}} void Graph::bfstravel () {memset (visited, 0, sizeof (int) *vertexnum), for (int i = 0; i < Vertexnum; i++) {if (!visited[i]) { BFS (i); cout << Endl;}}}

Time Complexity of O (v+e)

Depth First (DFS)

Depth-First search forms a depth-first forest of several depth-priority trees, each of which is called a tree edge. In addition, the depth traversal has a timestamp for each node that identifies when that node started to access and end access. An important feature is that the discovery and completion times have a bracket structure.

The code is as follows:

Depth-first traversal of void Graph::d fs (int s) {Visited[s] = 1;time + = 1;begintime[s] = time;cout << s << "(" << Beginti Me[s] << "";              Shengnode *p = Edges[s].next;while (P! = NULL) {if (!visited[p->val]) DFS (p->val);p = P->next;} Time + = 1;endtime[s] = Time;topsort.push_back (s); cout << Endtime[s] << ") <<" ";} void Graph::d fstravel () {memset (visited, 0, sizeof (int) *vertexnum), memset (beginTime, 0, sizeof (int) *vertexnum);  Node Start Access time memset (endTime, 0, sizeof (int) *vertexnum);    Node end access time for (int i = 0; i < Vertexnum; i++) {if (!visited[i]) {DFS (i); cout << Endl;}}

Time complexity O (v+e)

Attention:

For depth-first traversal, its edges can also be divided into 4 classes.

(1) tree edge, deep traversal of each edge of the forest is the edge of the tree.

(2) Forward edge, u to its descendants of non-tree side (u,v).

(3) Reverse edge, u to the side of its ancestor (U,V).

(4) Transverse side, one vertex is not the ancestor or descendant of another vertex.

Property: (1) A forward graph is a non-loop, when and only if the depth-first search on the graph does not produce a reverse edge

(2) in the process of depth-first searching for a graph G, each edge of G is either a tree edge or a reverse edge.

Topological sorting

Topological sequencing of a forward-free graph (dag,directed acyclic graph) is an application of depth-first search. Topological ordering is a linear sequence of all the vertices of figure g, and if you have an edge (u,v) in Figure G, the vertex U is in front of the vertex v. In many applications, there is a non-loop graph used to illustrate the sequence of events occurring.

The basic idea of the algorithm: by depth-first traversal of the DAG graph to get the time to complete the access to each node, the reverse is the topological ordering of the Dag graph.

The code is as follows: already reflected in the deep traversal.

The time complexity is O (v+e).

Strongly connected branches

The strongly connected branch is another classic application of depth-first search. A strongly connected branch of the g= (V,e) is a subset of the maximum vertex c which is V, so that any two vertices in C can reach each other

The transpose of Figure G: gt= (V,et), et={(u,v):(u,v) ∈e}. The ET is made up of the side of G that changes direction. The time complexity required to build the GT is also O (v+e)

The basic idea of the algorithm: first, a depth-first search of the graph G, the topological ordering sequence of the graph G is obtained, and then the graph GT is traversed in depth by this sequence, and the parentheses structure is all the strongly connected branches. time complexity is still O (v+e)

The code is as follows:

Create transpose void Graph::buildtransgraph (graph &g) {this->vertexnum = G.vertexnum;this->edgesnum = G.edgesNum of Figure G; for (int i = 0; i < Vertexnum; i++) {This->vertex[i] = G.vertex[i];this->edges[i].val = g.edges[i].val;this->ed Ges[i].weight = G.edges[i].weight;this->edges[i].next = NULL;} for (int i = 0; i < Vertexnum; i++) {Gnode *p = G.edges[i].next;while (P! = NULL) {Gnode *newnode = new Gnode (); newnode-&gt ; val = I;newnode->next = Null;newnode->weight = p->weight; Gnode *q = &edges[p->val];while (q->next! = NULL) Q = q->next;q->next = Newnode;p = P->next;}              }}//strongly connected component void Graph::componentsc () {//time = 0;//dfstravel ();        A deep search of Figure g takes the time required to complete X-access and thus obtains its topological sort graph g2;g2.buildtransgraph (*this); Get the transpose of Figure g time = 0;memset (g2.visited, 0, sizeof (int) *vertexnum) cout << "Strong connected component:" << endl;for (vector<int& Gt;::reverse_iterator iter = Topsort.rbegin (); Iter! = Topsort.rend (); iter++) {//G2 deep Search for transpose graph to get strong connected component if (!g2.visited[*iter]) G2.dfs (*iter);} cout << Endl;}

Full code:

Graph.h

#ifndef graph_h#define graph_h#include <iostream> #include <vector>using namespace std; #define MaxSize 10# Define MAXINT 0x80000000//Set this value to the maximum value of the weight of the struct gnode{int val;int weight; Gnode *next;}; Class graph{public:void Creategraph (int n, int e), void Destroygraph (Gnode *p), ~graph () {for (int i = 0; i < vertexnum; i+ +) {destroygraph (edges[i].next);//cout << "destructor:" << i << Endl;}}      void Showgraph (); void Bfstravel ();      Breadth traversal void dfstravel ();   Deep traversal of void showtopsort ();      Output topological sequence void componentsc ();      Establish a strong connected component of Figure G void Prim ();p rivate:int vertex[maxsize];    Storage vertex Gnode edges[maxsize];        Store adjacency table int vertexnum;          Vertex number int edgesnum;       Number of edges//BFS and DFS traversal int visited[maxsize];void BFS (int s); void Dfs (int s); int begintime[maxsize];          Depth start Access x time int endtime[maxsize];      Time to end access x static int time;vector<int> topsort;   The reverse order of Topsort is a topological sort with no loop buildtransgraph (Graph &g); Build the transpose of Figure G//Primint lowcost[maxsize];}; #endif 

Graph.cpp

#include <iostream> #include "graph.h" #include <queue>using namespace Std;int graph::time = 0;void Graph:: Creategraph (int n, int e) {vertexnum = N;edgesnum = e;for (int i = 0; i < n; i++) {Vertex[i] = I;edges[i].val = I;edges[i] . Weight = 0;edges[i].next = NULL;} for (int i = 0; i < e; i++) {int source, dest, wei;cin >> source >> dest >> Wei; Gnode *newnode = new Gnode (); newnode->val = Dest;newnode->weight = Wei;newnode->next = NULL; Gnode *p = &edges[source];while (p->next! = NULL) p = P->next;p->next = newnode;//No direction graph the paragraph is deleted/*gnode *newnode2 = new Gnode (); newnode2->val = Source;newnode2->weight = Wei;newnode2->next = NULL; Gnode *p2 = &edges[dest];while (p2->next! = NULL) P2 = P2->next;p2->next = newnode2;*/}}void Graph::d estroygr APh (Gnode *p) {if (p = = NULL) return;else{destroygraph (p->next);d elete p;}} void Graph::showgraph () {for (int i = 0; i < Vertexnum; i++) {int J = i;cout << i << "--";Gnode *p = Edges[j].next;while (P! = NULL) {cout << ("<< p->val <<", "<< p->weight <&lt ; ")";p = P->next;} cout << Endl;}} Breadth traversal diagram void Graph::bfs (int s) {queue<int> Q;q.push (s); Visited[s] = 1;while (!q.empty ()) {int u = q.front (); Q.pop (); cout << u << ""; Gnode *p = Edges[u].next;while (P! = NULL) {if (!visited[p->val]) {//is not accessed, it is added to the queue and is marked as visited Q.push (P->val); visited[ P->val] = 1;} p = P->next;}}} void Graph::bfstravel () {memset (visited, 0, sizeof (int) *vertexnum), for (int i = 0; i < Vertexnum; i++) {if (!visited[i]) { BFS (i); cout << Endl;}}} Depth-first traversal of void Graph::d fs (int s) {Visited[s] = 1;time + = 1;begintime[s] = time;cout << s << "(" << Beginti              Me[s] << ""; Shengnode *p = Edges[s].next;while (P! = NULL) {if (!visited[p->val]) DFS (p->val);p = P->next;} Time + = 1;endtime[s] = Time;topsort.push_back (s); cout << Endtime[s] << ") <<" ";} void Graph::d fstravel () {memSet (visited, 0, sizeof (int) *vertexnum), memset (beginTime, 0, sizeof (int) *vertexnum);    Node Start Access time memset (endTime, 0, sizeof (int) *vertexnum); Node end access time for (int i = 0; i < Vertexnum; i++) {if (!visited[i]) {DFS (i); cout << Endl;}} Output topology sort void Graph::showtopsort () {for (Vector<int>::reverse_iterator iter = Topsort.rbegin (); ITER! = Topsort.rend (); ITER + +) cout << *iter << ""; cout << Endl;} Create transpose void Graph::buildtransgraph (graph &g) {this->vertexnum = G.vertexnum;this->edgesnum = G.edgesNum of Figure G; for (int i = 0; i < Vertexnum; i++) {This->vertex[i] = G.vertex[i];this->edges[i].val = g.edges[i].val;this->ed Ges[i].weight = G.edges[i].weight;this->edges[i].next = NULL;} for (int i = 0; i < Vertexnum; i++) {Gnode *p = G.edges[i].next;while (P! = NULL) {Gnode *newnode = new Gnode (); newnode-&gt ; val = I;newnode->next = Null;newnode->weight = p->weight; Gnode *q = &edges[p->val];while (q->next! = NULL) Q = Q->next;q->next= Newnode;p = P->next;}              }}//strongly connected component void Graph::componentsc () {//time = 0;//dfstravel ();        A deep search of Figure g takes the time required to complete X-access and thus obtains its topological sort graph g2;g2.buildtransgraph (*this); Get the transpose of Figure g time = 0;memset (g2.visited, 0, sizeof (int) *vertexnum) cout << "Strong connected component:" << endl;for (vector<int& Gt;::reverse_iterator iter = Topsort.rbegin (); Iter! = Topsort.rend (); iter++) {//G2 deep Search for transpose graph to get strong connected component if (!g2.visited[*iter]) G2.dfs (*iter);} cout << Endl;}

Main.cpp

#include <iostream> #include "graph.h" using namespace Std;int Main () {graph g;g.creategraph (8); cout << " adjacency table: "<< endl;g.showgraph (); cout <<" breadth traversal results: "<< endl;g.bfstravel (); cout <<" Deep traversal results: "<< ; Endl;  with parentheses the result  where x (a B)  X represents the time at which node  a represents the start of Access X is the  time G.dfstravel () to complete the access X;                      The reverse of the time that the depth traversal is done accessing x is the sort of cout << topological sort: << endl;g.showtopsort (); G.COMPONENTSC (); return 0;}

Legend:

Waiting to be passed ...

Input:

0 1 1
1 2 1
2 0 1
1 3 1
3 4 1
4 3 1
2 5 1
5 6 1
6 5 1
3 6 1
6 7 1
7 7 1
4 7 1

Output:


where 0 (1 2 (2 3) 4) indicates that the NO. 0 node in the deep traversal begins to access the node at 1, the end of the access node is the time for the 4;2 node to start accessing 2, and the end access time is 3.

Algorithm Series note 6 (algorithm one for graphs-search, topological sort, and strongly connected branch)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.