Tarjan algorithm: This algorithm solves the cut points and bridge (cut edge) of a graph.

Source: Internet
Author: User
Tags cve

Tarjan algorithm: This algorithm solves the cut points and bridge (cut edge) of a graph.

Introduction:

The cut edge and cut point are defined only in an undirected graph. We can solve all the cut points and cut edges of an undirected graph by defining the brute force method, but this method is less efficient. Tarjan proposed a quick solution to solve all the cut points and cut edges in the plot using a DFS.

You are welcome to discuss it. please correct me if any errors exist.

If you need to reprint, please indicate the source http://www.cnblogs.com/nullzx/

1. Definition of cut point and bridge (cut edge)

In an undirected graph, the cut edge and cut point are defined.

Cut Point: In an undirected connected graph, remove a vertex and all its adjacent edges. When the number of connected components in the graph increases, the vertex is called a cut point.

Bridge (cutting edge): Remove an edge from the undirected link graph. If the number of connected components in the graph increases, this edge is called a bridge or cut edge.

Relationship between a cut point and a bridge (cut edge):

1) A cut point may not have a bridge, but a cut point may exist.

2) The bridge must be the edge attached to the cut point.

Vertex C is a cut point, but the side connected to vertex C is not a bridge.

2. brute-force solutions: solving the cut point set and cut edge set

The principle of the violence law is to solve the cut points and cut edges by defining them. Remove a vertex from the graph and perform DFS traversal. If the connected component increases, the vertex is the cut point. If an edge is removed from the graph and DFS traversal is performed, the edge is cut if the connected component increases. After performing the preceding operation on each vertex or edge, we can find all the cut points and cut edges of the graph. We call it the cut point set and cut edge set of the graph.

In specific code implementation, you do not need to delete the vertex and delete all edges attached to the vertex. For a cut point, we only need to set the accessed mark of the vertex to true before DFS, and then perform DFS from other vertices as the root. For edge Cutting, we only need to disable DFS from this edge. If the UNICOM component increases, this edge is the cut edge.

3. Principle of the Tarjan Algorithm

To determine whether a vertex is a cut point, in addition to its definition, it can also be viewed from the perspective of DFS (depth-first traversal. We first define two concepts through DFS.

Suppose we access vertex V from vertex U in DFS (vertex V has not been accessed yet), then we call vertex U as vertex VParent Vertex, V is UChild Vertex. Vertices that have been accessed before vertex U are called U'sAncestor Vertex.

Obviously, if all child vertices of vertex U can access the ancestor vertices of U without passing through the parent vertex U, removing vertex U does not affect the graph connectivity, and U is not a cut point. On the contrary, if at least one child vertex exists in vertex U, the parent vertex U must be used to access the ancestor vertex of U, after removing the vertex U, the ancestor vertex of vertex U is not connected to the Child vertex, indicating that U is a cut point.

 

The arrows in indicate the order of DFS access (instead of Directed Graph). For vertex D, the child vertex of D can return to the ancestor vertex C of D through the red edge of connected area 1 (in this case, C has been accessed). Therefore, D is not a cut point.

In Connection Area 2, vertices must pass through D to access the ancestor vertex of D. Therefore, D is the cut point. Once again, the arrow only indicates the access sequence of DFS, rather than the directed graph.

Here we also need to consider a special situation, that is, the root vertex of DFS (usually the vertex numbered 0), because the root vertex has no ancestor vertex. In fact, whether the root vertex is a cut point is also very good judgment, if starting from the root vertex, a DFS can access all the vertices, then the root vertex is not a cut point. If there are still unaccessed vertices after tracing back to the root vertex, You need to perform DFS again on the adjacent vertex, and the root vertex is the cut point.

4. Implementation Details of the Tarjan Algorithm

In the specific implementation of the Tarjan algorithm, we need to define three arrays dfn [], low [], and parent [] in DFS (depth-first traversal).

 

4.1Dfn Array

The subscript of the dnf array indicates the vertex number. The value in the array indicates the traversal Order (or timestamp) of the vertex in the DFS. Each time an unaccessed vertex is accessed, the value of the access order (timestamp) is increased by 1.The dfn value of the Child vertex must be greater than the dfn value of the parent vertex.(But not necessarily 1 larger, for example, if the parent vertex has two or more branches ). After accessing a vertex, its dfn value is determined and will not be changed.

 

4.2Low Array

The subscript of the low array indicates the vertex number, and the value in the array indicates the vertex in the DFS.FailedThe smallest sequence value (or timestamp) in the ancestor vertex that the parent vertex can access ).

The initial low value of each vertex should be the same as the dfn value. In DFS, we constantly update the low value as needed.

Assume that vertex U accesses vertex V. When V is traced back to the vertex U,

If

Dfn [v] <low [u]

So

Low [u] = dfn [v]

If the vertex U still has its branch, and each branch performs the above operation during backtracking, the vertex low [u] indicates the earliest ancestor node that can be accessed without the parent node of the vertex U.

 

4.3Parent Array

Parent []: subscript indicates the vertex number. The value in the array indicates the parent vertex number of the vertex. It is mainly used to exclude the parent vertex when updating the low value, of course, you can also implement the same function in other ways.

 

4.4A specific example

Let's look at an example. The simulation program calculates the dfn value and low value of each vertex. The blue solid-line arrow in indicates the path that has been accessed, and the zero-line arrow indicates the path that has not been accessed. Visited vertices are marked in yellow, unaccessed vertices are marked in white, and vertices currently being processed by DFS are marked in green. The blue dotted line with arrows indicates the return path for DFS backtracking.

 

1)

When DFS reaches the vertex H, there are three branches,Let's assume we leave the H-I first, then the H-F, and finally the H-J.. When I was accessed from H, vertex I was not accessed, So I's dfn and low are both 9. Based on the DFS traversal order, we should continue to access from vertex I.

 

2)

It indicates that vertex D is accessed by vertex I, and it is found that D has been accessed.

Dfn [D] <dfn [I]

Note that D is the ancestor vertex of I, so until now, vertex I can access a small timestamp of 4 without passing through the parent vertex H.

 

3)

Based on the DFS principle, we return from vertex I to vertex H, obviously, the minimum timestamp that vertex H can access so far is also 4 (because we only know that we can access D through I ), so low [H] = 4

 

4)

Now we continue to execute DFS, go through the H-F path and find that vertex F has been accessed and dfn [F] <dfn [H], indicating that F is the ancestor vertex of H, however, in this case, the earliest timestamp that vertex H can access is 4, while the timestamp of F is 6, and the definition of low [H] is still 4 based on the low value.

 

5)

Finally we go through the H-J path, vertex J has not been accessed so dfn [J] = 10 low [J] = 10

 

6)

Similarly, DFS accesses vertex B, dfn [J]> dfn [B], and B is the ancestor vertex, the earliest timestamp that vertex J can access without passing through the parent vertex H is dfn [B], that is, low [J] = 2.

 

7)

From vertex J back to vertex H, apparently, the earliest timestamp that vertex H can access so far is updated to 2 (because we have learned that we can access J from H so far), so low [H] = 2

 

8)

 

Based on the DFS principle, we roll back from H to vertex E (the process from H to G, G to F, and F to E is omitted), and the passing vertex will update the low value, because these vertices can be connected to vertex B without having to use their parent vertex. When you trace back to vertex e, there are still unaccessed vertices, then continue with the dfs of the E-K branch.

 

9)

The dfn and low values of vertex k and L are shown when accessing vertex l from the E-K Branch

 

10)

Then we continue to trace back to vertex D (the intermediate process is omitted) and update low [D].

 

11)

Finally, based on the DFS principle, we rolled back to vertex A and obtained the dfn and low values of each vertex.

 

4.5Method for Determining Cut points and bridges

Cut Point: Determine whether the vertex U is a cut point. Compare the dnf value of the vertex U with the low value of all its child vertices, if at least one child vertex V satisfies low [v]> = dnf [u], it means that vertex V must access the ancestor vertex of vertex U through vertex U, but there is no other path from vertex V to vertex U, so vertex U is a cut point. For vertices without child vertices, it is obviously not a cut point.

Bridge (cutting edge): Low [v]> dnf [u] indicates that the V-U is a bridge

It must be noted that the Tarjan algorithm can obtain the cut vertex set and cut edge set from any vertex of the graph for DFS.

From the results we can see that vertex B, vertex E and vertex K are cut points, A-B and E-K are cut edges.

 

5. Code Implementation
Package datastruct; import java. io. bufferedReader; import java. io. file; import java. io. fileNotFoundException; import java. io. fileReader; import java. io. printWriter; import java. io. reader; import java. io. stringWriter; import java. util. using list; import java. util. list; import java. util. vertex; public class CutVerEdge {/* used to mark the accessed vertex */private boolean [] marked;/* the role of the three arrays is not explained */private int [] low; private int [] dfn; p Rivate int [] parent;/* indicates whether it is a cut point */private boolean [] isCutVer;/* indicates the container that stores the Cut Point Set */private List <Integer> listV; /* The container storing the cut edge stores arrays. Each array has only two elements, indicating the two vertices attached to the edge */private List <int []> listE; private UndirectedGraph ug; private int visitOrder;/* timestamp variable * // * defines the edges of the graph */public static class Edge {/* Start vertex of the edges */private final int from; /* Edge termination vertex */private final int to; public Edge (int from, int to) {this. from = from; this. to = to;} public int fro M () {return this. from;} public int to () {return this. to;} public String toString () {return "[" + from + "," + to + "]" ;}} /* define an undirected graph */public static class UndirectedGraph {private int vtxNum;/* Number of vertices */private int edgeNum; /* Number of edges * // * adjacent table */private vertex list <Edge> [] adj;/* undirected graph constructor, which constructs a graph using a txt file, value not authorized */@ SuppressWarnings ("unchecked") public UndirectedGraph (Reader r) {BufferedReader br = new BufferedReader (r); Scanner scn = New vertex (br);/* Number of vertices in the graph */vtxNum = scn. nextInt ();/* Number of edges in the graph */edgeNum = scn. nextInt (); adj = (partition list <Edge> []) new partition list [vtxNum]; for (int I = 0; I <vtxNum; I ++) {adj [I] = new vertex list <Edge> () ;}/ * undirected graph, with the same Edge added twice */for (int I = 0; I <edgeNum; I ++) {int from = scn. nextInt (); int to = scn. nextInt (); Edge e1 = new Edge (from, to); Edge e2 = new Edge (to, from); adj [from]. add (e1); adj [to]. add (e2);} scn. close ();}/ * Graph Display Method */@ Overridepublic String toString () {StringWriter sw = new StringWriter (); PrintWriter pw = new PrintWriter (sw); for (int I = 0; I <vtxNum; I ++) {pw. printf ("%-3d:", I); for (Edge e: adj [I]) {pw. print (e);} pw. println ();} return sw. getBuffer (). toString ();}/* Number of returned vertices */public int vtxNum () {return vtxNum;}/* Number of returned edgeNum */public int edgeNum () {return edgeNum ;}} public CutVerEdge (UndirectedGraph ug) {this. ug = Ug; marked = new boolean [ug. vtxNum ()]; low = new int [ug. vtxNum ()]; dfn = new int [ug. vtxNum ()]; parent = new int [ug. vtxNum ()]; isCutVer = new boolean [ug. vtxNum ()]; listV = new sort list <Integer> (); listE = new sort list <int []> ();/* Call depth-first traversal, solve the dfn and low values of each vertex */dfs ();} private void dfs () {int childTree = 0; marked [0] = true; visitOrder = 1; parent [0] =-1; for (Edge e: ug. adj [0]) {int w = e. to (); if (! Marked [w]) {marked [w] = true; parent [w] = 0; dfs0 (w ); /* Whether the edge connected to the root vertex is a bridge */if (low [w]> dfn [0]) {listE. add (new int [] {0, w}) ;}childtree ++ ;}}/* process the root vertex separately */if (childTree> = 2) {/* The root vertex is the condition of the cut point */isCutVer [0] = true ;}}/* Other conditions except the root vertex */private void dfs0 (int v) {dfn [v] = low [v] = ++ visitOrder; for (Edge e: ug. adj [v]) {int w = e. to (); if (! Marked [w]) {marked [w] = true; parent [w] = v; dfs0 (w); low [v] = Math. min (low [v], low [w]);/* judge the cut point */if (low [w]> = dfn [v]) {isCutVer [v] = true;/* judge the bridge */if (low [w]> dfn [v]) {listE. add (new int [] {v, w}) ;}} elseif (parent [v]! = W & dfn [w] <dfn [v]) {low [v] = Math. min (low [v], dfn [w]) ;}}/* returns all cut points */public List <Integer> allCutVer () {for (int I = 0; I <isCutVer. length; I ++) {if (isCutVer [I]) {listV. add (I) ;}} return listV;}/* return all cut edges */public List <int []> allCutEdge () {return listE ;} /* determine whether vertex v is a cut point */public boolean isCutVer (int v) {return isCutVer [v];} public static void main (String [] args) throws FileNotFoundException {File path = new File (System. getProperties (). getProperty ("user. dir ")). getParentFile (); File f = new File (path, "algs4-data/tinyG2.txt"); FileReader fr = new FileReader (f); UndirectedGraph ug = new UndirectedGraph (fr); System. out. println ("\ n ------- graph's adjacent representation -------"); System. out. println (ug); System. out. println ("\ n ------- cut point in the graph -------"); CutVerEdge cve = new CutVerEdge (ug); for (int I: cve. allCutVer () {System. out. println (I);} System. out. println ("\ n ------- cut edge in the graph -----"); for (int [] a: cve. allCutEdge () {System. out. println (a [0] + "" + a [1]) ;}}

 

Running result

------ Graph adjacent representation ------- 0: [0, 5] [0, 1] [0, 2] [0, 6] 1: [1, 0] 2: [2, 0] 3: [3, 4] [3, 5] 4: [4, 3] [4, 6] [4, 5] 5: [5, 0] [5, 4] [5, 3] 6: [6, 4] [6, 7] [6, 9] [6, 0] 7: [7, 8] [7, 6] 8: [8, 7] 9: [9, 12] [9, 10] [9, 11] [9, 6] 10: [10, 9] 11: [11, 12] [11, 9] 12: [12, 9] [12, 11] ------- cut point in the graph ------- 0679 ------- cut edge in the graph ----- 7 86 79 106 90 10 2
6. References

Http://www.cnblogs.com/en-heng/p/4002658.html.

Http://blog.csdn.net/wtyvhreal/article/details/43530613.

[3]. http://www.cppblog.com/ZAKIR/archive/2010/08/30/124869.html? Opt = admin

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.