Tarjan la búsqueda de un punto de corte, corte de notas de estudio borde

Tarjan punto de la búsqueda de corte, el borde de corte

Permítanme hablar de lo que corte el punto?

Aprender el blog

Punto de corte sólo para gráfico conectado no dirigido, si un punto, y en la que todos los bordes que conectan los puntos retirados, la figura ya no está en comunicación, a continuación, el punto se denomina punto de corte;

Tarjan aprendido previamente para la búsqueda de los componentes fuertemente conectados del grafo dirigido, cuando el bajo [i] == dfn [i], i i pila en frente de la misma y forma un gráfico fuertemente conectado;

Buscando punto de corte y que es un poco diferente, dividido en dos casos:

  1. Cuando i es una raíz, si tiene más de dos subárboles (no hijos), luego se corta a un punto i determinado;
  2. Cuando i no es una raíz, (i, j) de un lado, si el bajo [j]> = dfn [i], i es el punto de corte;

plantilla:

El papel de la matriz de esta plantilla es en realidad para evitar un bucle infinito cuando bidireccional traversal borde, el equivalente de dfs (SN, grasa);

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]);
    }
}

Título de la plantilla:

Luo Gu P3388 [plantilla] punto de corte (corte superior)

código:

#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;
}

Permítanme ahora mira lo que es el borde de corte?

En el enlace no dirigido dibujo, se elimina un borde, se incrementa el número de componente conectado (es decir, no se comunican FIG), este borde se conoce como un puente o un borde de corte.

Punto de las relaciones de corte con el filo de corte (puente) es:

  1. No hay necesariamente un puente punto de corte, un puente debe existir punto de corte
  2. Puente debe ser el punto de unión del borde de corte.

Así que pedir y pedir a la vanguardia del punto de corte casi, o más bien exigir un punto de corte es buscar punta, filo, porque tiene que haber un punto de corte;

Los únicos requisitos con diferentes puntos de corte cuando el borde (i, j) que satisface bajo [j]> dfn [i] es el borde de corte, no es igual;

Título de la plantilla:

Luo Gu P1656 bombardeo de tren

código:

#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;
}
Publicados 264 artículos originales · alabanza won 46 · Vistas a 10000 +

Supongo que te gusta

Origin blog.csdn.net/qq_44291254/article/details/104944972
Recomendado
Clasificación