DFS tree

Statement section of this article content from a blog on codeforces , invasion deleted.

DFS is a common graph traversal methods.

Consider undirected graph traversal: we visit a node, traversing all of its neighboring nodes, if you do not have access to visit. Find that each node will only be visited once, that is accessible to all nodes and edges may constitute a tree, we call this tree for the DFS tree. Generating a visited side called side (span edge), it is referred to not have access to the edge (back edge).

DFS tree

After careful observation to the edge, we can find some properties:

  • After each connected only to the edge of ancestors and descendants, brothers will not be connected.

This is well documented, if there is an edge connecting the brothers, then we will first visit in the course of DFS in to one of the brothers, and then visit another brother through this edge, instead of returning the ancestors of the visit to go. That is that the edge must be generated edges.

  • Each corresponds to one side of the ring, each ring also corresponds to a rear side.

Proof is very evident, to complete the DFS tree by observing the way.

With these properties DFS tree can do it? The most classic application is the use of low Tarjan array to find cut points of the algorithm.

We consider under what circumstances non-root node \ (u \) is cut point:

  • When and only if there exists a son, so that the son node in the subtree there is no connection to an edge \ (U \) of ancestors, or after the edge is not crossed a (passes over) \ (U \) .

Proof is obvious, not repeat them.

Specific implementation, we let \ (dfn [u] \) represents \ (u \) is the first \ (dfn [u] \) months to be accessed, \ (Low [U] \) for the DFS tree \ ( u \) son (containing \ (u \) themselves) that all nodes have access to the \ (dfn \) minimal. Then for node \ (U \) , do the following:

procedure DFS(u)
    ind <- ind + 1
    dfn[u] <- low[u] <- ind

    childnum <- 0
    for v 可以被 u 访问
        if 访问过 v then low[u] <- min(low[u], dfn[v])
        else
            DFS(v)
            low[u] <- min(low[u], low[v])
            if low[v] = dfn[u] then childnum <- childnum + 1
            end if
        end if
    end for
    
    if childnum >= 1
        u 为割点
    end if
end procedure

Note that we only visit his son node, so no special sentenced father

For the root node, we need to have more than two of its sons. In a specific implementation can make \ (childnum = -1 \)

Gives C ++ implementation

Luo Gu board questions

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

const int maxn = 2E+4 + 5;
const int maxm = 1E+5 + 5;

int n, m, root;
int tot, first[maxn];
int ind, cnt, p[maxn];
int dfn[maxn], low[maxn];
struct Edge {
	int to, next;
} e[maxm * 2];

inline void Add(int x, int y)
{
	e[++tot] = { y, first[x] };
	first[x] = tot;
}

void DFS(int u)
{
	dfn[u] = low[u] = ++ind;
	
	int childnum = 0;
	if(u == root) childnum = -1;
	
	for(int i = first[u]; i; i = e[i].next) {
		int v = e[i].to;
		
		if(!dfn[v]) {
			DFS(v), low[u] = min(low[u], low[v]);
			if(low[v] == dfn[u]) ++childnum;
		}
		else low[u] = min(low[u], dfn[v]);
	}
	
	if(childnum >= 1) p[++cnt] = u;
}

int main()
{
	scanf("%d%d", &n, &m);
	for(int i = 1; i <= m; ++i) {
		int x, y;
		
		scanf("%d%d", &x, &y);
		Add(x, y), Add(y, x);
	}
	
	for(int i = 1; i <= n; ++i)
		if(!dfn[i]) root = i, DFS(i);
	
	sort(p + 1, p + cnt + 1);
	
	printf("%d\n", cnt);
	for(int i = 1; i <= cnt; ++i)
		printf("%d\n", p[i]);
}

In fact, the DFS may also be processed without the tree into a directed graph of the class of bipartite graph partitioning things, especially when dealing cactus is handy to FIG.

Guess you like

Origin www.cnblogs.com/whx1003/p/12635387.html