Tarjan seeking a cut point, cutting edge study notes

Tarjan seeking cut point, cutting edge

Let me talk about what point cut?

Learning blog

Cutpoint only for undirected connected graph, if a point, and in which all the edges connecting the points removed, FIG no longer in communication, then the point is called cut point;

Tarjan learned previously for Finding the strongly connected components of the directed graph, when the low [i] == dfn [i], i i stack in front of it and forms a strongly connected graph;

Seeking cut point and that is a bit different, divided into two cases:

  1. When i is a root, if it has more than two subtrees (not sons), then cut to a certain point i;
  2. When i is not a root, (i, J) of one side, if the low [j]> = dfn [i], i is the cut point;

template:

The role of parent of this template is actually to prevent an infinite loop when two-way edge traversal, the equivalent of dfs (sn, fat);

const int V = 20;
int dfn[V], low[V], parent[V];
bool vis[V], ap[V];
vector<int> g[V];

void dfs(int u)
{
    static int count = 0;
    // 子树数量
    int children = 0;

    // 默认low[u]等于dfn[u]
    dfn[u] = low[u] = ++count;
    vis[u] = true;

    // 遍历与u相邻的所有顶点
    for (int v: g[u])
    {
        // (u, v)为树边
        if (!vis[v])
        {
            // 递增子树数量
            children++;
            // 设置v的父亲为u
            parent[v] = u;
            // 继续DFS
            dfs(v);
            // DFS完毕,low[v]已求出,如果low[v]<low[u]则更新low[u]
            low[u] = min(low[u], low[v]);

            // 如果是根节点且有两棵以上的子树则是割点
            if (parent[u] == -1 && children >= 2)
                cout << "Articulation point: " << u << endl;
            // 如果不是根节点且low[v]>=dfn[u]则是割点
            else if (parent[u] != -1 && low[v] >= dfn[u])
                cout << "Articulation point: " << u << endl;
        }
        // (u, v)为回边,且v不是u的父亲
        else if (v != parent[u])
            low[u] = min(low[u], dfn[v]);
    }
}

Template title:

Luo Gu P3388 [template] point cut (top cut)

Code:

#include<bits/stdc++.h>
#define LL long long
#define pa pair<int,int>
#define ls k<<1
#define rs k<<1|1
#define inf 0x3f3f3f3f
using namespace std;
const int N=20010;
const int M=1000100;
const LL mod=100000000;
int dfn[N],low[N],tot,head[N],cnt,n,m,vis[N];
struct Node{
	int to,nex;
}edge[M];
void add(int p,int q){
	edge[cnt].to=q;
	edge[cnt].nex=head[p];
	head[p]=cnt++;
}
void Tarjan(int p,int fa){
	dfn[p]=low[p]=++tot;
	int ch=0;//儿子数量 
	for(int i=head[p];~i;i=edge[i].nex){
		int q=edge[i].to;
		if(!dfn[q]){
			Tarjan(q,p);
			low[p]=min(low[p],low[q]);
			if(p!=fa&&low[q]>=dfn[p]) vis[p]=1;
			if(p==fa) ch++;
		}
		low[p]=min(low[p],dfn[q]);
	}
	if(ch>=2&&p==fa) vis[p]=1;
}
int main(){
	memset(head,-1,sizeof(head));
	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]) continue;
		Tarjan(i,i);
	}
	int ans=0;
	for(int i=1;i<=n;i++) if(vis[i]) ans++;
	cout<<ans<<endl;
	for(int i=1;i<=n;i++) if(vis[i]) printf("%d ",i);
    return 0;
}

Let me now look what is cutting edge?

In the drawing undirected link, an edge is removed, the number of connected component is increased (i.e. do not communicate FIG), this edge is referred to as a bridge or a cutting edge.

Point cut relations with the cutting edge (bridge) is:

  1. There is not necessarily a cut-point bridge, a bridge must exist cutpoint
  2. Bridge must be the point of attachment of the cut edge.

So ask and beg on the cutting edge of the cutting point almost, or rather demand a cut point is to seek cutting edge, cutting edge because there must be a cut point;

The only requirements with different cut points when the edge (i, j) satisfying low [j]> dfn [i] is the cutting edge, not equal;

Template title:

Luo Gu P1656 railway bombing

Code:

#include<bits/stdc++.h>
#define LL long long
#define pa pair<int,int>
#define ls k<<1
#define rs k<<1|1
#define inf 0x3f3f3f3f
using namespace std;
const int N=20010;
const int M=1000100;
const LL mod=100000000;
int dfn[N],low[N],tot,head[N],cnt,n,m,cc;
struct Ans{
	int u,v;
}ans[M];
bool cmp(Ans p,Ans q){
	if(p.u==q.u) return p.v<q.v;
	return p.u<q.u;
}
struct Node{
	int to,nex;
}edge[M];
void add(int p,int q){
	edge[cnt].to=q;
	edge[cnt].nex=head[p];
	head[p]=cnt++;
}
void Tarjan(int p,int fa){
	dfn[p]=low[p]=++tot;
	for(int i=head[p];~i;i=edge[i].nex){
		int q=edge[i].to;
		if(!dfn[q]){
			Tarjan(q,p);
			low[p]=min(low[p],low[q]);
			if(low[q]>dfn[p]){
				if(p>q) ans[++cc].u=q,ans[cc].v=p;
				else ans[++cc].u=p,ans[cc].v=q;
			}
		}
		else if(q!=fa) low[p]=min(low[p],dfn[q]);//这个条件特别关键 
	}
}
int main(){
	memset(head,-1,sizeof(head));
	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]) Tarjan(i,i);
	} 
	sort(ans+1,ans+cc+1,cmp);
	for(int i=1;i<=cc;i++) cout<<ans[i].u<<" "<<ans[i].v<<endl;
    return 0;
}
Published 264 original articles · won praise 46 · views 10000 +

Guess you like

Origin blog.csdn.net/qq_44291254/article/details/104944972