Boost graph: Iterating through all vertices and printing adjacent vertices - c++

I want to print all vertices with their adjacent vertices. I found some examples online on how to do that, yet it won't work for me. I am getting the error, that the ++ operator cannot be used on ai. Also I think it needs to be vertex_idMap[*ai] and not vertex_idMap[ai] but this prompts an error. Does anyone know why this is wrong?
typedef adjacency_list<vecS, listS, directedS, VertexIDPorperty, EdgeWeight> Graph; //the type of g
graph_traits <Graph>::vertex_iterator i, end;
graph_traits <Graph>::adjacency_iterator ai, a_end;
for (boost::tie(i, end) = vertices(g); i != end; ++i) {
std::cout << vertex_idMap[*i];
for (; ai != a_end; ++ai) { //the ++ai seems to be wrong?
std::cout << vertex_idMap[ai];
if (boost::next(ai) != a_end)
std::cout << ", ";
}
std::cout << std::endl;

Observations:
Where's the rest of the code? It obviously depends on the types used.
ai and a_end aren't initialized (perhaps you didn't actually mean the code doesn't compile, and this was your whole problem)
vertex_idMap[ai] will not compile, as a vertex_iterator is not a valid vertex_descriptor
Here's a fixed example with the missing bits imagined:
Live On Coliru
#include <boost/graph/adjacency_list.hpp>
#include <iostream>
using VertexIDPorperty = boost::property<boost::vertex_index_t, int>;
using EdgeWeight = boost::property<boost::edge_weight_t, double>;
typedef boost::adjacency_list<boost::vecS, boost::listS, boost::directedS, VertexIDPorperty, EdgeWeight> Graph;
Graph sample();
int main() {
Graph g = sample();
auto vertex_idMap = get(boost::vertex_index, g);
boost::graph_traits <Graph>::vertex_iterator i, end;
boost::graph_traits <Graph>::adjacency_iterator ai, a_end;
for (boost::tie(i, end) = vertices(g); i != end; ++i) {
std::cout << vertex_idMap[*i] << ": ";
for (boost::tie(ai, a_end) = adjacent_vertices(*i, g); ai != a_end; ++ai) {
std::cout << vertex_idMap[*ai];
if (boost::next(ai) != a_end)
std::cout << ", ";
}
std::cout << std::endl;
}
}
Implementing sample() to create a random graph:
#include <boost/graph/random.hpp>
#include <random>
Graph sample() {
Graph g;
std::mt19937 prng { std::random_device{}() };
generate_random_graph(g, 10, 20, prng);
int id = 0;
for (auto vd : boost::make_iterator_range(vertices(g))) {
put(boost::vertex_index, g, vd, ++id);
}
return g;
}
It prints something like:
1: 9, 9, 4
2: 6
3:
4:
5: 9, 9, 8, 9
6: 9, 3, 1
7: 2, 10
8: 6
9: 8
10: 7, 3, 8, 1, 4
Out Of The Box
Printing a graph can be done simpler:
#include <boost/graph/graph_utility.hpp>
// ...
int main() {
print_graph(sample());
}
Live On Coliru
1 -->
2 --> 3 10 9 6 6 10
3 --> 8
4 -->
5 --> 4
6 --> 1 5 8
7 --> 4 9 2 2 1
8 --> 6
9 --> 5 7
10 --> 7

Related

Boost Kruskal minimum spanning tree algorithm -- undirected vs directed graph documentation

Per the documentation, the minimum spanning tree algorithm implemented in boost should work only on undirected graphs. Yet, the following code that provides a directed graph as input to the algorithm seems to work just fine: (while building on MSVC Visual Studio 2019, there are no warnings related to boost)
#include <boost/property_map/property_map.hpp>
#include <boost/config.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/kruskal_min_spanning_tree.hpp>
#include <boost/graph/graph_utility.hpp>
using namespace boost;
typedef adjacency_list <vecS, vecS, directedS, no_property,
property<edge_weight_t, double>>
Graph_vvd_MST;
typedef adjacency_list_traits<vecS, vecS, directedS> Traits_vvd;
property_map<Graph_vvd_MST, edge_weight_t>::type cost;
typedef Traits_vvd::edge_descriptor Edge;
std::vector < Edge > spanning_tree;
int main() {
Graph_vvd_MST g;
add_vertex(g);//0 th index vertex
add_vertex(g);// 1 index vertex
add_vertex(g);// 2 index vertex
cost = get(edge_weight, g);
//Add directed arcs
for(int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++) {
if (i == j)
continue;
std::pair<Traits_vvd::edge_descriptor, bool> AE = add_edge(i, j, g);
assert(AE.second);
if (i == 0 && j == 1) cost[AE.first] = 1;
if (i == 0 && j == 2) cost[AE.first] = 2;
if (i == 1 && j == 0) cost[AE.first] = 1;
if (i == 1 && j == 2) cost[AE.first] = 2;
if (i == 2 && j == 0) cost[AE.first] = 1;
if (i == 2 && j == 1) cost[AE.first] = 2;
}
kruskal_minimum_spanning_tree(g, std::back_inserter(spanning_tree));
printf("MST Solution:\n");
for (std::vector < Edge >::iterator ei = spanning_tree.begin();
ei != spanning_tree.end(); ++ei) {
int fr = source(*ei, g);
int to = target(*ei, g);
double cst = cost[*ei];
printf("[%d %d]: %f \n", fr, to, cst);
}
getchar();
}
The code above generates the following bidirectional graph:
The output of the code is correctly:
MST Solution:
[0 1]: 1.000000
[2 0]: 1.000000
Is it the case that the document is not updated and in recent boost versions, the algorithm can actually work with directed graphs?
I'd simplify the code Live
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/kruskal_min_spanning_tree.hpp>
#include <iostream>
using Graph =
boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS,
boost::no_property,
boost::property<boost::edge_weight_t, double>>;
using Edge = Graph::edge_descriptor;
int main()
{
Graph g(3); // 0..2
/*auto [it, ok] =*/ add_edge(0, 1, {1}, g);
add_edge(0, 2, {2}, g);
add_edge(1, 0, {1}, g);
add_edge(1, 2, {2}, g);
add_edge(2, 0, {1}, g);
add_edge(2, 1, {2}, g);
auto cost = get(boost::edge_weight, g);
std::vector<Edge> spanning_tree;
kruskal_minimum_spanning_tree(g, std::back_inserter(spanning_tree));
std::cout << "MST Solution:\n";
for (auto e : spanning_tree) {
std::cout << e << ": " << cost[e] << "\n";
}
}
If you insist on a loop to insert edges: Live
for (auto [i, j, c] : { std::tuple //
{0, 1, 1.},
{0, 2, 2.},
{1, 0, 1.},
{1, 2, 2.},
{2, 0, 1.},
{2, 1, 2.},
})
{
if (!add_edge(i, j, {c}, g).second)
return 255;
}
The Question
If you don't meet the documented pre-conditions the output is unspecified. Unspecified doesn't mean it throws an exception (that would be specified). It might even accidentally (seem to) do the right thing.
The point is that the algorithm operates under the assumption that edges are - by definition - traversable in the reverse direction at the same cost. As soon as you deviate from that, the algorithm may give incorrect results. In fact, some algorithms might exhibit undefined behaviour (like, a Dijkstra with some weights negative might never complete).
You'd do better to
Either convert your graph to be undirected
satisfy the invariants of undirected graphs and verify that the algorithm works correctly for it
Use an algorithm for MDST (Minimum Directed Spanning Tree), see e.g. Finding a minimum spanning tree on a directed graph

How to use Boost MST Algorithm on a complete Graph [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
I am very new to the BGL. I have the following problem: I've got a very large complete Graph and weights for every edge and need to evaluate a Minimum Spanning Tree.
I would like to use the Boost Graph Libraries implementation. What structures should I use to represent my complete graph and how would I call the Algorithm? Also I'd like to store the resulting subgraph in some graph structure so that I can perform different operations on the MST afterwards.
Thank you very much.
Here's a simple example. I'd suggest an adjacency matrix since the graph is going to be complete, so the matrix is very dense.
using Graph =
boost::adjacency_matrix<boost::undirectedS, boost::no_property,
boost::property<boost::edge_weight_t, double>>;
using Vertex = Graph::vertex_descriptor;
using Edge = Graph::edge_descriptor;
Now let's create a graph
int main() {
Graph g(23);
Picking an arbitrary number (23) of vertices for this example. Let's use randomly generated weights:
auto weight_distribution = std::bind(
std::lognormal_distribution<>{0, 0.25},
std::mt19937{std::random_device{}()});
Creating all the edges to make the graph complete:
for (Vertex v = 0; v < num_vertices(g); ++v)
for (Vertex u = v + 1; u < num_vertices(g); ++u)
add_edge(v, u, 100*weight_distribution(), g);
Now, let's use Prim's algorithm (since all the weights are non-negative):
std::vector<Vertex> parent(num_vertices(g));
prim_minimum_spanning_tree(g, parent.data());
This writes the predecessor for each vertex in the parent vector (which is called the predecessor map).
Adding Some Output
For more interesting results, let's add some checks and output:
assert(std::ranges::all_of(
make_iterator_range(edges(g)),
[ew = get(boost::edge_weight, g)](auto e) { return ew[e] > 0; }));
Making sure the data satisfies the weight pre-condition. You might also do a completeness check depending on how you get your input data.
std::vector<Vertex> parent(num_vertices(g));
std::map<Vertex, double> distance;
auto root = vertex(0, g); // or just 0
Let's pass the optional arguments distance_map and root_vertex:
prim_minimum_spanning_tree(g, parent.data(),
boost::root_vertex(root)
.distance_map(boost::make_assoc_property_map(distance)));
That uses named parameters (starting with boost::root_vertex and chaining with .other_parameter(...).even_more(...). You can of course start with any named parameter).
Now we can use the recorded data:
double total_path_weight = 9;
for (Vertex v = 0; v < num_vertices(g); ++v) {
auto p = parent[v];
auto weight = distance[v];
std::cout << p << " -> " << v << " weight " << weight
<< (p == v ? " ROOT" : "") << "\n";
total_path_weight += weight;
}
std::cout << "Total path weight " << total_path_weight << "\n";
DEMO
Live On Coliru
#include <boost/graph/adjacency_matrix.hpp>
#include <boost/graph/prim_minimum_spanning_tree.hpp>
#include <random>
#include <iostream>
using Graph =
boost::adjacency_matrix<boost::undirectedS, boost::no_property,
boost::property<boost::edge_weight_t, double>>;
using Vertex = Graph::vertex_descriptor;
using Edge = Graph::edge_descriptor;
using boost::make_iterator_range;
int main() {
Graph g(23);
auto weight_distribution = std::bind(std::lognormal_distribution<>{0, 0.25},
std::mt19937{std::random_device{}()});
for (Vertex v = 0; v < num_vertices(g); ++v)
for (Vertex u = v + 1; u < num_vertices(g); ++u)
add_edge(v, u, 100*weight_distribution(), g);
assert(std::ranges::all_of(
make_iterator_range(edges(g)),
[ew = get(boost::edge_weight, g)](auto e) { return ew[e] > 0; }));
std::vector<Vertex> parent(num_vertices(g));
std::map<Vertex, double> distance;
auto root = vertex(0, g); // or just 0
prim_minimum_spanning_tree(g, parent.data(),
boost::root_vertex(root)
.distance_map(boost::make_assoc_property_map(distance)));
double total_path_weight = 9;
for (Vertex v = 0; v < num_vertices(g); ++v) {
auto p = parent[v];
auto weight = distance[v];
std::cout << p << " -> " << v << " weight " << weight
<< (p == v ? " ROOT" : "") << "\n";
total_path_weight += weight;
}
std::cout << "Total path weight " << total_path_weight << "\n";
}
Printing e.g.
0 -> 0 weight 0 ROOT
15 -> 1 weight 64.6241
21 -> 2 weight 62.1609
1 -> 3 weight 69.207
5 -> 4 weight 71.9255
2 -> 5 weight 68.3983
14 -> 6 weight 66.6639
17 -> 7 weight 69.5045
20 -> 8 weight 78.9941
6 -> 9 weight 69.3287
4 -> 10 weight 62.7512
0 -> 11 weight 65.9305
15 -> 12 weight 70.2627
4 -> 13 weight 67.9708
22 -> 14 weight 73.3816
14 -> 15 weight 61.069
6 -> 16 weight 63.5795
5 -> 17 weight 66.0981
6 -> 18 weight 54.6061
14 -> 19 weight 73.9725
5 -> 20 weight 74.7002
0 -> 21 weight 71.8757
17 -> 22 weight 68.6378
Total path weight 1504.64

Dividing an STL list container to elements greater than value and elements lower than value

I'm making a function that recieves as parameter a list and a value K the function should divide the list to two parts the first part, in the same list without using another container contains the elements that are lower than the value K, the second part contains elements that are greater or equal to K, here's my attempt:
template <class T>
void dividie_list(list<T> & mylist, T k){
list<int>::iterator it;
it = mylist.begin();
while(it != mylist.end()){
if(*it >= k){
mylist.push_back(*it);
it = mylist.erase(it);
}
else
++it;
}
}
Input output example:
Input : mylist={1,3,4,14,11,9,7,16,25,19,7,8,9 } y k=8
Output: {1, 3, 4, 7, 7,9, 11, 16, 25, 19, 14, 8, 9}
It seems that the function gets stuck in an infinite loop and doesn't end, I can't figure that out, final exams are close guys, help is appreciated.
Edit: i tried something else based on a suggested solution but i can't tell for sure if it's valid, can someone confirm it :
template <class T>
void dividie_list(list<T> & mylist, T k)
{
typename list<T>::iterator first = mylist.begin();
typename list<T>::iterator last = mylist.end();
--last;
while(first != last){
if(*first >= k){
swap(*first,*last);
--last;
}
else
++first;
}
}
If you want the implementation of the method instead of calling a function to do the job, here is what you want, based on the code on this page.
#include <list>
#include <algorithm>
#include <iostream>
using namespace std;
template <class T>
void dividie_list(list<T> & mylist, T k)
{
typename list<T>::iterator first = mylist.begin();
typename list<T>::iterator last = mylist.end();
while (first!=last)
{
while (*first < k)
{
++first;
if (first==last) return;
}
do
{
--last;
if (first==last) return;
} while (!(*last < k));
swap (*first,*last);
++first;
}
return ;
}
Driver program to test above function:
int main()
{
int a[] = {1,3,4,14,11,9,7,16,25,19,7,8,9 };
list<int> l(a, a + sizeof(a) / sizeof(int) );
copy(l.begin(), l.end(), ostream_iterator<int>(cout, ", ") );
cout<<'\n';
dividie_list(l, 8);
copy(l.begin(), l.end(), ostream_iterator<int>(cout, ", ") );
}
the output is as below:
1, 3, 4, 14, 11, 9, 7, 16, 25, 19, 7, 8, 9,
1, 3, 4, 8, 7, 7, 9, 16, 25, 19, 11, 14, 9,
You need to return an iterator instead of void so that you can know where is the boundary between the first part and second.
There is no need to push or pop items anywhere. Enumerating the list and swapping elements as needed is all that is required.
#include <iostream>
#include <algorithm>
#include <iterator>
#include <vector>
#include <list>
// iterator based parition implementation.
template<typename Iter>
Iter divide_list(Iter begin, Iter end,
const typename std::iterator_traits<Iter>::value_type& val)
{
Iter p = begin;
for (Iter it = begin; it != end; ++it)
{
if (*it < val)
{
if (it != p)
{
std::cout << "Swapping " << *it << " and " << *p << '\n';
std::iter_swap(it, p);
}
++p;
}
}
return p;
}
// generic container wrapper
template<template<typename, typename...> class V, typename T, typename... Args>
void divide_list(V<T,Args...>& seq, const T& arg)
{
divide_list(std::begin(seq), std::end(seq), arg);
}
int main()
{
std::list<int> lst { {1,3,4,14,11,9,7,16,25,19,7,8,9 } };
for (auto x : lst)
std::cout << x << ' ';
std::cout << std::endl;
divide_list(lst, 8);
for (auto x : lst)
std::cout << x << ' ';
std::cout << '\n' << std::endl;
// also works with vector (and deque)
std::vector<int> vec { {6,4,9,14,11,2,7,9,25,16,7,8,3 } };
for (auto x : vec)
std::cout << x << ' ';
std::cout << std::endl;
divide_list(vec, 8);
for (auto x : vec)
std::cout << x << ' ';
std::cout << std::endl;
return 0;
}
Output
1 3 4 14 11 9 7 16 25 19 7 8 9
Swapping 7 and 14
Swapping 7 and 11
1 3 4 7 7 9 14 16 25 19 11 8 9
6 4 9 14 11 2 7 9 25 16 7 8 3
Swapping 2 and 9
Swapping 7 and 14
Swapping 7 and 11
Swapping 3 and 9
6 4 2 7 7 3 14 9 25 16 11 8 9
As a bonus, I modified the iterator algorithm to return the iterator position p as the function result, thereby knowing the first element in the resulting sequence that is greater-than or equal-to the test value (may come in handy). This allow you to have a start/end of the low-sequence (lst.begin(), p) and for the high sequence (p, lst.end()). The generic container support was solely because I was bored.

graph levelization using BGL

Can you please post example code to levelize a directed graph using BGL?
Definition of levelization: Vertex has a property "int level". During BFS traversal of the graph, when a vertex is being "examined", look at its predecessor vertices' levels, take max of these, increment, and assign this to the "level" of this vertex.
If you mean the BFS depth then this is already built in to boost BFS and can be gotten easily.
Just use a vector to store the depths and a depth BFS visitor like this example I made:
#include <iostream>
#include <vector>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/breadth_first_search.hpp>
using namespace std;
using namespace boost;
typedef adjacency_list < vecS, vecS, directedS,
property< vertex_index_t, size_t> ,
property< edge_index_t, size_t > > Graph;
typedef graph_traits<Graph>::vertex_descriptor Vertex;
typedef graph_traits<Graph>::edge_descriptor Edge;
int main(int argc, char* argv[]){
Graph G;
vector<Vertex> verts;
for(size_t i = 0; i < 9; ++i){
Vertex v = add_vertex(G);
verts.push_back(v);
}
/*
0 0
/ \
1 1 4
/ \
2 2 5
/ \
3 3 6
\
4 7
\
5 8
*/
add_edge(verts.at(0),verts.at(1),G);
add_edge(verts.at(1),verts.at(2),G);
add_edge(verts.at(2),verts.at(3),G);
add_edge(verts.at(0),verts.at(4),G);
add_edge(verts.at(4),verts.at(5),G);
add_edge(verts.at(5),verts.at(6),G);
add_edge(verts.at(6),verts.at(7),G);
add_edge(verts.at(7),verts.at(8),G);
cout << "vertices " << num_vertices(G) << endl;
cout << "edges " << num_edges(G) << endl;
//store depths
vector<size_t> d(num_vertices(G));
//get an index map, from Graph definition property< vertex_index_t, size_t>
typedef boost::property_map< Graph, boost::vertex_index_t>::type VertexIndexMap;
VertexIndexMap v_index = get(boost::vertex_index, G);
// Create the external property map, this map wraps the storage vector d
boost::iterator_property_map< std::vector< size_t >::iterator, VertexIndexMap >
d_map(d.begin(), v_index);
//Start at 0
boost::breadth_first_search(G, verts.at(0),
boost::visitor(boost::make_bfs_visitor(
boost::record_distances(d_map, boost::on_tree_edge())
)));
cout << "Starting at 0" << endl;
for(size_t i = 0; i < 9; ++i){
//depth (level) of BFS
cout << "vertex " << i << "\t" << d.at(i) << endl;
}
vector<size_t> d2(num_vertices(G));
cout << "Starting at 4" << endl;
// Create the external property map, this map wraps the storage vector d
boost::iterator_property_map< std::vector< size_t >::iterator, VertexIndexMap >
d2_map(d2.begin(), v_index);
//start at 4
boost::breadth_first_search(G, verts.at(4),
boost::visitor(boost::make_bfs_visitor(
boost::record_distances(d2_map, boost::on_tree_edge())
)));
for(size_t i = 0; i < 9; ++i){
//depth (level) of BFS
cout << "vertex " << i << "\t" << d2.at(i) << endl;
}
}
Output should look like this:
vertices 9
edges 8
Starting at 0
vertex 0 0
vertex 1 1
vertex 2 2
vertex 3 3
vertex 4 1
vertex 5 2
vertex 6 3
vertex 7 4
vertex 8 5
Starting at 4
vertex 0 0
vertex 1 0
vertex 2 0
vertex 3 0
vertex 4 0
vertex 5 1
vertex 6 2
vertex 7 3
vertex 8 4
When you start at 4 the other vertices are not reachable (directed) so the vector contains default values (0 in this case). This should work for undirected too.

I'm trying to use this Boost C++ code and I have a problem

First I'll explain, then I'll paste the code. I actually copied the code from this example
http://www.boost.org/doc/libs/1_45_0/libs/graph/example/prim-example.cpp
And then I'm trying to get it to work with an input from a text file, just like I did for the Boost Kruskal algorithm.
Using the debugger, I know that the second argument of this function wants the "end" the array of edges. That's what I'm giving it with my function call, i don't understand.
Graph g(edges, edge_array + num_edges, weights, num_nodes);
I get this error
1>c:\users\edmond\documents\visual studio 2008\projects\boost prim algo\boost prim algo\main.cpp(61) : error C2661: 'boost::adjacency_list<OutEdgeListS,VertexListS,DirectedS,VertexProperty,EdgeProperty>::adjacency_list' : no overloaded function takes 4 arguments
1> with
1> [
1> OutEdgeListS=boost::vecS,
1> VertexListS=boost::vecS,
1> DirectedS=boost::undirectedS,
1> VertexProperty=boost::property<boost::vertex_distance_t,int>,
1> EdgeProperty=boost::property<boost::edge_weight_t,int>
1> ]
Here is the full code. I have commented the original code, but you can also find the original code on the website I gave.
//=======================================================================
// Copyright 2001 Jeremy G. Siek, Andrew Lumsdaine, Lie-Quan Lee,
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
#include <boost/config.hpp>
#include <iostream>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/prim_minimum_spanning_tree.hpp>
int
main()
{
using namespace boost;
typedef adjacency_list < vecS, vecS, undirectedS,
property<vertex_distance_t, int>, property < edge_weight_t, int > > Graph;
typedef std::pair < int, int >E;
//const int num_nodes = 5;
//E edges[] = { E(0, 2), E(1, 3), E(1, 4), E(2, 1), E(2, 3),
// E(3, 4), E(4, 0)
//};
//int weights[] = { 1, 1, 2, 7, 3, 1, 1 };
//int num_edges = 7;
//Lire un fichier contenant les 2 structures de données
int num_nodes = 0;
std::size_t num_edges = 0;
int * weights;
E * edge_array;
static char ligne[50]; //Ligne lue
bool premiereLignefaite = false;
FILE* fichier = fopen("graph_poids.txt", "r");
int i = 0;
while (fgets(ligne, 50, fichier) != NULL) //retourne 0 quand on a end-of-file
{
//La premiere ligne est différente
if (premiereLignefaite == false) {
//Initialiser une matrice d'adjacence NxN
sscanf(ligne, "%d %d", &num_nodes, &num_edges );
edge_array = new E[num_edges];
weights = new int[num_edges];
premiereLignefaite = true;
continue;
}
//On construit notre liste d'arêtes
int sommet1, sommet2, poids;
sscanf(ligne, "%d %d %d", &sommet1, &sommet2, &poids);
weights[i] = poids;
edge_array[i].first = sommet1;
edge_array[i].second = sommet2;
i++;
}
E* machin = edge_array + num_edges; //aller au dernier élément
Graph g(edges, edge_array + num_edges, weights, num_nodes);
//Graph g(edges, edges + sizeof(edges) / sizeof(E), weights, num_nodes);
property_map<Graph, edge_weight_t>::type weightmap = get(edge_weight, g);
std::vector < graph_traits < Graph >::vertex_descriptor >
p(num_vertices(g));
prim_minimum_spanning_tree(g, &p[0]);
for (std::size_t i = 0; i != p.size(); ++i)
if (p[i] != i)
std::cout << "parent[" << i << "] = " << p[i] << std::endl;
else
std::cout << "parent[" << i << "] = no parent" << std::endl;
return EXIT_SUCCESS;
}
Here is some test data if you want to try it. The name of the file is graph_poids.txt
14 19
0 2 4
0 4 9
0 1 7
1 6 2
2 3 6
3 5 7
3 4 4
4 13 9
5 7 7
5 6 6
6 8 9
6 10 4
7 9 4
7 8 7
8 11 7
8 10 7
9 12 7
9 11 10
12 13 5
It should be "edge_array" and not "edges" (that one was part of the original code).