J'ai récemment appris l'algorithme de temps linéaire pour calculer les points d'articulation dans un graphique. Ma mise en œuvre s'exécute correctement sur un test en ligne Judge Test Data afin qu'il n'y ait pas de problème avec le code. Cependant, il semble que j'ai de la difficulté à comprendre comment le même point d'articulation survient plus d'un dans la série DFS. Laissez-moi vous expliquerPoints d'articulation apparaissant à plusieurs reprises dans l'implémentation de Tarjan
J'ai une liste qui stocke les points d'articulation si elles sont rencontrées. Maintenant, quand j'imprime la liste à la fin, j'obtiens les bons points d'articulation mais quelques sommets qui sont des points d'articulation se produisent plus d'une fois dans la liste. Selon moi, cela ne devrait pas se produire puisque nous ne rencontrons chaque sommet qu'une seule fois. Alors, pourquoi suis-je obtenir des entrées répétées dans la liste? Pour résoudre ceci, j'ai utilisé un HashSet dans mon code original pour les stocker et j'ai juste imprimé le contenu à la fin qui a donné la bonne réponse. Voici mon code avec le problème. L'algorithme est principalement basé sur l'pseudocode sur wikipedia ici: https://en.wikipedia.org/wiki/Biconnected_component
Voici mon code pour le implmentation en C++:
/*input
7 6
0 1
1 2
3 4
2 4
2 6
5 2
*/
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define pb emplace_back
#define sz 3005 //In the current scenario, I need only a maximum on 3000 vertices
typedef long long int ll;
//Created by Shreyans Sheth [bholagabbar]
bool visited [sz]; //whether the node has been discoverd in the DFS run or not
int low [sz]; //time of the earliest discovered vertex reachable from the vertex
int disc [sz]; //time at which vertex was explored
int parent [sz]; //stores the parents of each vertex
vector<int> a[sz]; //Adjacency List for graph
int rtime; //Time
vector<int> ap; //Stored the articulation points
void DFS(int s)
{
visited[s]=1;
low[s]=disc[s]=++rtime;
int nchild=0;
for(auto i:a[s])
{
if(!visited[i])
{
nchild++;//INcrement children of the current vertex
parent[i]=s;
DFS(i);
low[s]=min(low[s],low[i]);
/* s is an articulation point iff
1. It the the root and has more than 1 child.
2. It is not the root and no vertex in the subtree rooted at one of its
children has a back-link to its ancestor.
A child has a back-link to an ancestor of its parent when its low
value is less than the discovery time of its parent.*/
if((parent[s]==-1 && nchild>1)||(parent[s]!=-1 && low[i]>=disc[s]))
ap.pb(s);//Adding the articulation points. How are they repeated?
}
else if(visited[i] && i!=parent[s])
low[s]=min(low[s],disc[i]);
}
}
void ArticulationPoints(int n)//Driver Funtion
{
ap.clear();
rtime=0;//The time for each cycle of DFS
for(int i=0;i<n;i++)
{
parent[i]=-1;//Initializing parents as -1. True for roots
visited[i]=0;//All points not visited
low[i]=disc[i]=INT_MAX;
}
for(int i=0;i<n;i++)
if(!visited[i])//Vertex not discoverdd
DFS(i);
}
int main()
{
int n,m;//number of vertices, edges
cin>>n>>m;
for(int i=0;i<m;i++)//Building Graph
{
int x,y;
cin>>x>>y;
a[x].pb(y);
a[y].pb(x);
}
ArticulationPoints(n);//Calculating Articulation points
cout<<"Articulation Points are:\n";
for(int i:ap)
cout<<i<<endl;
return 0;
}
Code avec entrée et sortie: http://ideone.com/u5dYOy (voir comment les deux vient trois fois?)
Pourquoi cela se produit-il? Ai-je manqué quelque chose dans l'algorithme? Je crois avoir une idée juste du fonctionnement de l'algorithme. Toute aide est appréciée. Merci
Merci! J'ai vérifié et l'instruction if à l'extérieur l'a corrigé. De plus, bits/stdC++ permet d'économiser beaucoup de temps dans la programmation des compétitions. Je suis conscient que c'est une mauvaise pratique dans le développement logiciel – bholagabbar
A propos de la partie pseudo-code, j'ai pris référence à partir d'une implémentation réelle [ici] (https://github.com/kartikkukreja/blog-codes/blob/master/src/Articulation% 20Points% 20ou% 20Cut% 20Vertices% 20with% 20DFS.cpp). Cela a augmenté le temps pour chaque noeud. Donc j'ai fait la même chose. Je n'aurais pas d'importance, n'est-ce pas? Aussi, si je devais suivre le pseudo-code et passer le paramètre 'd' à chaque fois, quelle valeur de 'd' passerais-je pour chaque condition 'if' réussie dans la fonction 'ArticulationPoint'? – bholagabbar
@bholagabbar vous avez raison, il semble que pour cet algorithme, 'd' peut être le temps de découverte (ce que vous faisiez) ou la profondeur (ce que j'ai suggéré). Cela n'a pas d'importance ici. Si vous utilisiez un paramètre 'd', vous appelleriez' DFS' avec 'd = c' à chaque fois depuis' ArticulationPoint', où 'c' est une constante (c'est généralement 0 ou 1). – IVlad