因此,我在Biconnected Components (BCC)
中计算undirected graph
,在计算之后,我的算法也在某些BCC中也包含了一些Bridge
边,因此作为后处理步骤,我运行了一个循环在每个BCC
(表示为vector<pair<int, int>>
,每个pair<int, int>
代表该BCC中的edge
上)。这是我的操作方式:
auto pred = [&Bridges](pair<int, int>& edge) -> bool
{
return Bridges.find(edge) != Bridges.end();
};
for (auto bcc = BCC.begin(); bcc != BCC.end(); bcc++)
{
vector<pair<int, int>>& BCCList = (bcc->second);
BCCList.erase(remove_if(
BCCList.begin(), BCCList.end(), pred), BCCList.end());
}
Bridges
再次是set
中的pair<int, int>
,其中包含我的算法找到的所有Bridge边缘。
BCC
是unordered_map<int, vector<pair<int, int>>>
。
上面的代码按预期工作,删除了之前在BCC向量中可能存在的所有Bridge边缘。但是,如果我稍作更改,然后执行以下操作:
auto pred = [&Bridges](pair<int, int>& edge) -> bool
{
return Bridges.find(edge) != Bridges.end();
};
for (auto bcc = BCC.begin(); bcc != BCC.end(); bcc++)
{
vector<pair<int, int>> BCCList = (bcc->second);
BCCList.erase(remove_if(
BCCList.begin(), BCCList.end(), pred), BCCList.end());
}
我所做的就是在&
的第一行中删除BCCList
之前的for-loop
。这使代码无法正常工作,并且产生的结果好像从未执行过该for-loop
一样;没有删除任何BCC中的桥边缘,从而最终计算出错误的BCC。请告诉我为什么会这样?
我一直以为,如果我在bcc
上有一个像unordered_map
这样的迭代器,那么bcc->first
是key
(这里bcc->first
应该是int
和bcc->second
是value
(此处,bcc->second
应该是vector<pair<int, int>>
)。这不正确吗?为什么我必须明确指定&
(参考变量)才能使代码正常工作?
这种行为也许与remove_if
有关吗?
答案 0 :(得分:6)
vector<pair<int, int>>& BCCList = (bcc->second);
在这里,BCCList
是存储在bcc->second
中的向量的引用(备用名称)。您对BCCList
所做的任何更改实际上都是对bcc->second
所做的。
vector<pair<int, int>> BCCList = (bcc->second);
在这里,BCCList
是存储在bcc->second
中的向量的副本。这是一个单独的对象。对其所做的更改根本不会影响bcc->second
。
这是一个简单的示例,应该更清楚地说明正在发生的事情:
int data = 42;
int *bcc = &data;
int &ref = *bcc;
ref = 314;
int cop = *bcc;
cop = -42;
我认为您不希望作业cop = -42;
修改data
。在您的代码中,情况完全相同。
答案 1 :(得分:3)
在您的原始代码中,BCCList
是对BCC中某个元素的引用。您在BCCList
上所做的一切,实际上都是在原始元素上完成的。
删除&
时,BCCList
是一个独立的值,并使用原始副本进行初始化。您对它所做的所有操作都保留在该值的局部值,并且在下一次迭代时(或在退出循环时)会丢失。