hihoCoder #1183 : Connectivity 1. Cut edge and cut point (template)

#1183 : Connectivity 1. Cut edges and cut points

(Template: Find cutting edges and cutting points)

topic link

The meaning of the question: Given a connected graph, find all the cut points and cut edges, and directly output Null if there is no cut point.

Ideas:

In the dfs tree:
cut point: 1. This point is the root node of the dfs tree. If the root node has two or more subtrees, it is the cut point
      2. This point is not the root node of the dfs tree. If v is the child node of u. If low[v]>=dfn[u], it means that the child node v of u can return to the ancestor node u at most, but cannot return to the ancestor node of u. At this time, this is also a node.

Cut edge: For an edge <u, v>, if v is a child node of u, and low[v]>dfn[u], it means that the child node v of u cannot return to the node u, at this time it is <u, v> is a cut edge.

The following definitions are reproduced from hihoCoder



Cut edge : In a connected graph, after deleting an edge of the connected graph, the graph is no longer connected. Such edges are called cut edges, also known as bridges.

Cut point : In a connected graph, after deleting a certain point of the connected graph and the edge connected to this point, the graph is no longer connected. Such points are called cut points.

DFS search tree : When traversing the graph with DFS, according to the different traversal order, we can get a DFS search tree.

Tree edge : shown by the blue line in the search tree , it can be understood as the edge that is passed when visiting unvisited nodes in the DFS process , also known as parent-child edge

Back edge : shown by the orange line in the search tree , it can be understood as the edge passed when the visited node is encountered in the DFS process , also known as atavistic edge, backward edge

#include<bits/stdc++.h>
using namespace std;
const int maxn = 200000 + 10;
struct Edge {
	int u, v;
};
bool cmd(Edge &a,Edge &b) {
	if(a.u==b.u)
		return a.v<b.v;
	else
		return a.u<b.u;
}
struct Tarjan {// Tarjan 模板
	int n;
	vector<int>e[maxn];    //边集
	int dfn[maxn]; //The dfn array is a timestamp, which is the time when the node was accessed, that is, how many times to call the dfs function
	int low[maxn]; //Low is the minimum value of the node DFN that the child of u can reach through the reverse edge, the initial value is dfn[u]
	int index; //record the number of dfs calls
	Edge edge[maxn]; //Record cutting edge
	int node[maxn]; //Record the cut point
	int f[maxn]; //parent node
	int s[maxn]; //Number of child nodes
	int cnt_edge; // number of edges to cut
	int cnt_node; //The number of points of the cut point
	void init(int N) { //initialization
		n = N;
		for (int i = 1; i <= n; i++)
			e[i].clear();
		index = 0;
		cnt_node=0;
		cnt_edge=0;
		memset(dfn, -1, sizeof(dfn));
		memset(f,0,sizeof(f));
		memset(s,0,sizeof(s));
	}
	void addedge(int u, int v) { //add edge
		e[u].push_back(v);
	}
	void dfs(int u) { //dfs is similar to the writing method of ring contraction point, two main arrays dfn[] and low[]
		dfn[u] = low[u] = ++index;
		bool flag=0;
		for (int i = 0; i<e[u].size(); i++) {
			int &v = e[u][i];
			if (dfn[v] == -1) {
				s[u]++;
				f[v]=u;
				dfs(v);
				if(low[v]>=dfn[u]) {
					flag=1;
				}
				if(low[v]>dfn[u]) { //low[v] greater than dfn[u] means that there is no other path to make v return to u except the original path, that is, a ring cannot be formed, so it is a cut edge
					edge[cnt_edge].u=min(u,v);
					edge [cnt_edge ++] .v = max (u, v);
				}
				low[u] = min(low[u], low[v]);
			} else if (v!=f[u])
				low[u] = min(low[u], dfn[v]);
		}
		if((f[u]==0&&s[u]>=2)||(f[u]&&flag)) // 1. This point is the root node of the dfs tree, if the root node has two or more subtree, then it is a cut point
			node[cnt_node++]=u; //2. This point is not the root node of the dfs tree. If there is a child node where v is u and low[v]>=dfn[u], it is also a cut point
	}
	void solve() { //traverse all points
		for (int i = 1; i <= n; i++) {
			if (dfn[i] == -1)
				dfs(i);
		}
	}

} T;
int main() {
	int n,m;
	int u, v;
	scanf("%d %d",&n,&m);
	T.init(n);
	for(int i=1; i<=m; i++) {
		scanf("%d %d",&u,&v);
		T.addedge(u,v);
		T.addedge(v,u);
	}
	T.solve();
	sort(T.edge,T.edge+T.cnt_edge,cmd);
	sort(T.node,T.node+T.cnt_node);
	if(T.cnt_node==0) {
		printf("Null\n");
		return 0;
	}
	for(int i=0; i<T.cnt_node; i++) {
		printf("%d%c",T.node[i],i==T.cnt_node-1?'\n':' ');
	}
	for(int i=0; i<T.cnt_edge; i++) {
		printf("%d %d\n",min(T.edge[i].u,T.edge[i].v),max(T.edge[i].u,T.edge[i].v));
	}
	return 0;
}


I have to say that the explanation on the original hiho is very well written. I laughing out loud recommend everyone to take a look at the official solution (should be)


Guess you like

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