我有这个代码来查找连接图中的桥:
void dfs (int v, int p = -1) {
used[v] = true;
tin[v] = fup[v] = timer++;
for (size_t i=0; i<g[v].size(); ++i) {
int to = g[v][i];
if (to == p) continue;
if (used[to])
fup[v] = min (fup[v], tin[to]);
else {
dfs (to, v);
fup[v] = min (fup[v], fup[to]);
if (fup[to] > tin[v])
printf("%d %d", v, to);
}
}
}
如何在不使用递归的情况下重写它?我知道,它可以这样做,我应该使用堆栈,但是这行必须在递归调用dfs()之后执行,而我无法通过堆栈实现:
fup[v] = min(fup[v], fup[to])
那么,如何迭代地重写我的算法呢?
答案 0 :(得分:4)
您想制作“堆叠框架”结构
struct Frame {
Frame(int v, int p, int i, Label label);
int v;
int p;
int i;
};
// constructor here
并且,如你所说,stack<Frame>
。在所有这些字段之间,可以模拟调用堆栈(未经测试的代码以提供一般概念)。
void dfs(int v, int p = -1) {
stack<Frame> st;
st.push(Frame(v, p, 0));
do {
Frame fr(st.top());
st.pop();
v = fr.v;
p = fr.p;
int i(fr.i);
if (i > 0) {
int to(g[v][i - 1]);
fup[v] = min(fup[v], fup[to]);
if (fup[to] > tin[v]) { printf("%d %d", v, to); }
if (i == g[v].size()) { continue; }
} else if (i == 0) {
used[v] = true;
tin[v] = fup[v] = timer++;
}
int to(g[v][i]);
if (to == p) { continue; }
if (used[to]) {
fup[v] = min(fup[v], tin[to]);
} else {
st.push(Frame(to, v, 0));
}
st.push(Frame(v, p, i + 1));
} while (!st.empty());
}
答案 1 :(得分:0)
对不起,我晚答复了。
更改先前答案的代码,现在可以正常使用了。 在竞赛任务中进行了测试,以查找连接的Graph中的所有桥。 希望对您有帮助。
// Copyright 2020 Kondratenko Evgeny
#include <iostream>
#include <vector>
#include <algorithm>
#include <stack>
struct Frame {
Frame(int v, int p, int i) : v(v), p(p), i(i) {
}
int v;
int p;
int i;
};
void DFS(int n,
const std::vector<std::vector<int>> &G,
const std::vector<std::vector<int>> &weights) {
std::vector<bool> used(n + 1, false);
std::vector<int> ret(n + 1); // the same as tup
std::vector<int> enter(n + 1); // the same as tin
std::stack<Frame> s;
s.push(Frame(1, -1, 0));
int time = 1;
while (!s.empty()) {
Frame f = s.top();
s.pop();
int v = f.v;
int p = f.p;
int i = f.i;
if (i == 0) {
enter[v] = ret[v] = time++;
used[v] = true;
}
// First part works befor DFS call
if (i < G[v].size()) {
int to = G[v][i];
s.push(Frame(v, p, i + 1));
if (to != p) {
if (used[to]) {
ret[v] = std::min(ret[v], enter[to]);
} else {
s.push(Frame(to, v, 0));
}
}
}
/*
Generally here is virtual DFS recursive call, which we are simulate now
*/
// Second part after DFS call
if (i > 0 && i <= G[v].size()) {
int to = G[v][i - 1];
if (to != p) {
ret[v] = std::min(ret[v], ret[to]);
if (ret[to] > enter[v]) {
std::cout << "bridge between: " << v << " and " << to;
std::cout << ", with weight: " << weights[v][i - 1] << std::endl;
}
}
}
}
}
int main() {
int n, m; // n - number of vertex, m - number of edges
std::cin >> n >> m;
std::vector<std::vector<int>> G(n + 1, std::vector<int>()); // your Graph
std::vector<std::vector<int>> weights(n + 1, std::vector<int>());
for (int i = 0; i < m; ++i) { // read edges with weigths
int u, v, w;
std::cin >> u >> v >> w;
G[u].push_back(v);
G[v].push_back(u);
weights[u].push_back(w);
weights[v].push_back(w);
}
DFS(n, G, weights);
return 0;
}