所以我目前正在研究一个单词阶梯问题的项目,我已经构建了用于存储所有字典单词并在其中添加边缘的图形,我使用boost图形库来完成。
但令我困惑的是breadth_first_search()
函数,看起来像参数只占用起始顶点但没有结束顶点。
我检查了文档并注意到我可以为该搜索功能定义BFS访问者,但由于我是升级库的新手,我无法弄清楚它是如何工作的。
有人能解释如何实现找到两个顶点之间的最短路径吗?我正在使用无向且未加权的图表。
#include <iostream> // std::cout
#include <fstream>
#include <string>
#include <stdlib.h>
#include <utility> // std::pair
#include "headers.h"
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/dijkstra_shortest_paths.hpp>
#include <boost/graph/graph_utility.hpp>
using namespace std;
//Define a class that has the data you want to associate to every vertex and
edge
//struct Vertex{ int foo;}
// struct Edge{std::string blah;}
struct VertexProperties {
string name;
VertexProperties(string name) : name(name) {}
};
//typedef property<edge_weight_t, int> EdgeWeightProperty;
//typedef property<vertex_name_t, string> VertexNameProperty;
//Define the graph using those classes
typedef boost::adjacency_list<boost::setS, boost::listS, boost::undirectedS,
VertexProperties> Graph;
typedef Graph::vertex_iterator Vit;
typedef Graph::vertex_descriptor Vde;
typedef Graph::edge_descriptor E;
typedef boost::graph_traits<Graph>::adjacency_iterator adjacency_it;
struct my_visitor : boost::default_dijkstra_visitor {
using base = boost::default_dijkstra_visitor;
struct done{};
my_visitor(Vde vd, size_t& visited) : destination(vd), visited(visited) {}
void finish_vertex(Vde v, Graph const& g) {
++visited;
if (v == destination)
throw done{};
base::finish_vertex(v, g);
}
private:
Vde destination;
size_t &visited;
};
//Some typedefs for simplicity
//typedef boost::graph_traits<Graph>::vertex_descriptor vertex_t;
//typedef boost::graph_traits<Graph>::edge_descriptor edge_t;
int main()
{
ifstream dictionary("dictionary.txt");
string word;
Graph allWords;
//Vit begin,end;
if(dictionary.is_open())
{
while(getline(dictionary,word))
{
word.pop_back();
add_vertex(VertexProperties(word),allWords);
}
}
else
cout<<"File openning failed."<<endl;
dictionary.close();
//cout<<num_vertices(allWords)<<endl;
Vit begin,end;
boost::tie(begin, end) = vertices(allWords);
vector<Graph::vertex_descriptor> vindex(begin, end);
int first=0;
int second=0;
for(Vit it=begin;it!=end;it++)
{
for(Vit that=it;that!=end;that++)
{
if(isEditDistanceOne(allWords[*it].name,allWords[*that].name))
add_edge(vindex[first],vindex[second],allWords);
second++;
}
first++;
second=first;
cout<<first<<endl;
}
//Vit temp=begin;
//temp++;
//cout<<allWords[*begin].name<<"////////////////"<<endl;
adjacency_it neighbour, neighbour_end;
for (tie(neighbour, neighbour_end) = adjacent_vertices(*begin, allWords);
neighbour != neighbour_end; ++neighbour)
cout<<allWords[*neighbour].name<<endl;
string firstWord;
string secondWord;
int firstIndex=-1;
int secondIndex=-1;
cout<<"Enter first word:"<<endl;
cin>>firstWord;
cout<<"Enter second word:"<<endl;
cin>>secondWord;
Vit a=begin;
for(int i=0;i<num_vertices(allWords);i++)
{
if(allWords[*a].name==firstWord)
{
firstIndex=i;
break;
}
a++;
}
Vit b=begin;
for(int i=0;i<num_vertices(allWords);i++)
{
if(allWords[*b].name==secondWord)
{
secondIndex=i;
break;
}
b++;
}
if(firstIndex==-1)
cout<<"First word not in graph."<<endl;
else if(secondIndex==-1)
cout<<"Second word not in graph."<<endl;
else
{
Vde start_vertex=vindex[firstIndex];
Vde end_vertex=vindex[secondIndex];
size_t visited;
std::vector<boost::default_color_type> colors(num_vertices(allWords),
boost::default_color_type{});
std::vector<Vde> _pred(num_vertices(allWords),
allWords.null_vertex());
std::vector<size_t> _dist(num_vertices(allWords),
-1ull);
my_visitor vis { end_vertex, visited };
auto predmap = _pred.data(); // interior properties:
boost::get(boost::vertex_predecessor, g);
auto distmap = _dist.data(); // interior properties:
boost::get(boost::vertex_distance, g);
try {
std::cout << "Searching from #" << start_vertex << " to #" << end_vertex
<<
"...\n";
boost::dijkstra_shortest_paths(allWords, start_vertex,
boost::visitor(vis).
color_map(colors.data()).
distance_map(distmap).
predecessor_map(predmap).
weight_map(boost::make_constant_property<E>(1ul))
);
std::cout << "No path found\n";
return 0;
} catch(my_visitor::done const&) {
std::cout << "Percentage skipped: " <<
(100.0*visited/num_vertices(allWords)) << "%\n";
}
}
//cout<<adjacency_list[*begin]<<"\t";
return 0;
}