我有一个用于查找MST的代码,其中包括给MST的给定路径,这给了我正确的MST权重(我知道输出应该是什么)。我试图重写代码的一部分以使用std::map
而不是std::vector
来进行更有效的查找(从下面的代码中可以清楚地看到),但是现在它给出了错误的答案,并且尽管调查了几个小时,我无法理解我在哪里犯了错误。定位错误的任何帮助将不胜感激。
使用vector<Edge>
的旧版本。遍历所有边的向量(m_all_edges
)。如果边e
在vector<Edge> path
中,则将其添加到MST(m_mst
)中。否则,将其添加到MST(m_edges
)的候选边缘。
void MSTPath::m_add_shortest_path_old(vector<Edge> path){
for (auto e : path){
m_graph->union_vu(e.get_node(),e.get_opposite_node(-1));
}
for (auto e : m_all_edges){
if (tempfunc(e,path)) m_mst.push_back(e);
else m_edges.push_back(e);
}
}
bool MSTPath::tempfunc(Edge e, vector<Edge> path){
for (auto edge : path){
if((edge.get_node()==e.get_node())&&(edge.get_opposite_node(-1)==e.get_opposite_node(-1))) return true;
}
return false;
}
带有std::map
的版本。
void MSTPath::m_add_shortest_path(map<Edge,int> path_map){
for (auto const& x : path_map){
Edge e = x.first;
m_graph->union_vu(e.get_node(),e.get_opposite_node(-1));
}
for (auto const& x : m_all_edges_map){
if ((path_map.count(x.first)>0)||(path_map.count(x.first.reversed())>0)) m_mst.push_back(x.first);
else m_edges.push_back(x.first);
}
}
查找MST的函数(在调用m_add_shortest_path
/ m_add_shortest_path_old
之后调用)。
int MSTPath::m_compute_mst(){
sort(m_edges.begin(),m_edges.end(),[](Edge e1, Edge e2) { return e1.weight < e2.weight; });
int i = 0;
int mst_size = m_mst.size();
int mst_weight = 0;
int v,u;
for (Edge e : m_mst) mst_weight += e.weight;
while (mst_size<m_N-1){
Edge edge = m_edges[i++];
v = m_graph->find(edge.get_node());
u = m_graph->find(edge.get_opposite_node(-1));
if (u!=v){
mst_size++;
mst_weight += edge.weight;
if (mst_weight>=min_mst_weight) return numeric_limits<int>::max();
m_mst.push_back(edge);
m_graph->union_vu(v,u);
}
}
return mst_weight;
}
从我看到的结果来看,两个函数都获得完全相同的m_mst
(并以mst_weight
开头)和相同的m_edges
(但顺序不同)。但是排序对于算法来说应该不是问题(除了按重量排序,但这是m_compute_mst
中的句柄),对吧?
Edge
类:
class Edge{
public:
Edge(int v_e, int u_e, int w){
v = v_e;
u = u_e;
weight = w;
}
int get_node() const { return v; }
int get_opposite_node(int k) const {
if ((k==v) || (k==-1)) return u;
else return v;
}
Edge reversed() const {
return Edge(u,v,weight);
}
bool operator<(const Edge& e) const {
if (this->get_node()<e.get_node()) return true;
else if (this->get_node()==e.get_node()) return this->get_opposite_node(-1)<e.get_opposite_node(-1);
else return false;
}
int v, u, weight;
};
是的,我知道按值传递会产生更多副本。这是一个临时版本。