// We do not need to define Q either, as we will loop over each vertex anyway, and the order does not matter.
// We do not need to define Q either, as we will loop over each vertex anyway, and the order does not matter.
vector<pair<int,double>>top_actors;// Each pair is (actor_index, farness).
vector<pair<int,double>>top_actors;// Each pair is (actor_index, farness).
top_actors.reserve(k+1);// We need exactly k items, no more and no less.
top_actors.reserve(k+1);// We need exactly k items, no more and no less.
vector<bool>enqueued(MAX_ACTOR_ID,false);// Vector to see which vertices with put in the queue during the BSF
vector<thread>threads;
// We loop over each vertex
mutextop_actors_mutex;// To prevent simultaneous accesses to top_actors
for(constauto&[actor_id,actor]:A){
threads.reserve(N_THREADS);
// if |Top| ≥ k and L[v] > Farn[Top[k]] then return Top; => We can not exploit the lower bound of our vertex to stop the loop, as we are not updating lower bounds L.
for(inti=0;i<N_THREADS;i++){
// We just compute the farness of our vertex using a BFS
intr=0;// |R|, where R is the set of vertices reachable from our vertex
if(!A.count(actor_id))// The actor must exist, otherwise A[actor_id] would attempt to write A, and this may produce a race condition if multiple threads do it at the same time
longlongintsum_distances=0;// Sum of the distances to other nodes
continue;
intprev_distance=0;// Previous distance, to see when we get to a deeper level of the BFS
// if |Top| ≥ k and L[v] > Farn[Top[k]] then return Top; => We can not exploit the lower bound of our vertex to stop the loop, as we are not updating lower bounds L.
q.push(make_pair(actor_id,0));
// We just compute the farness of our vertex using a BFS
enqueued[actor_id]=true;
queue<pair<int,int>>q;// FIFO of pairs (actor_index, distance from our vertex).
boolskip=false;
for(size_ti=0;i<enqueued.size();i++)
while(!q.empty()){
enqueued[i]=false;
auto[bfs_actor_id,distance]=q.front();
intr=0;// |R|, where R is the set of vertices reachable from our vertex
q.pop();
longlongintsum_distances=0;// Sum of the distances to other nodes
// Try to set a lower bound on the farness
intprev_distance=0;// Previous distance, to see when we get to a deeper level of the BFS
if(top_actors.size()==k&&distance>prev_distance){// We are in the first item of the next exploration level
q.push(make_pair(actor_id,0));
// We assume r = A.size(), the maximum possible value
if (top_actors[k-1].second<=farness_lower_bound){// Stop the BFS
while (!q.empty()){
skip=true;
auto[bfs_actor_id,distance]=q.front();
break;
q.pop();
}
// Try to set a lower bound on the farness
}
if(distance>prev_distance){
// We compute the farness of our vertex actor_id
constlock_guard<mutex>top_actors_lock(top_actors_mutex);// Acquire ownership of the mutex, wait if another thread already owns it. Release the mutex when destroyed.
r++;
if(top_actors.size()==k){// We are in the first item of the next exploration level
sum_distances+=distance;
// We assume r = A.size(), the maximum possible value
// We loop on the adjacencies of bfs_actor_id and add them to the queue
// Insert the actor in top_actors, before the first element with farness >= than our actor's (i.e. sorted insert)
constlock_guard<mutex>top_actors_lock(top_actors_mutex);// Acquire ownership of the mutex, wait if another thread already owns it. Release the mutex when destroyed.