【发布时间】:2019-11-26 18:07:12
【问题描述】:
我们有 n 个顶点(其中 n 小于 100 000)和 m 个随机边(其中 m 小于 10 000 000)。我们想找到两个给定顶点之间的路径。如果没有路径,我们将只打印 -1。 我的算法是建立一棵树。每个顶点都有一个 disjoint_index (i),表示所有具有 disjoint_index (i) 的顶点都是连通的。
disjoint_index 的默认值是每个顶点的索引。在顶点 v 和 u 之间找到一条边后,我检查它们是否连接。如果它们是连接的,我什么也不做。否则,我会通过一个名为 (dfs) 的函数更改 u 的 disjoint_index 以及连接到 u 的所有顶点。
下面是用c++构建这棵树的函数代码:
struct vertex{
int disjoint_index;
vector<int> adjacent;
};
void build_tree(int m, int s, int e)
{
for(int i = 0; i < m; i++)
{
int u = kiss() % n;
int v = kiss() % n;
if(disjoint_counter[u] > disjoint_counter[v])
{
int temp = u;
u = v;
v = temp;
}//counter v > u
if(ver[v].disjoint_index != ver[u].disjoint_index)
{
ver[v].adjacent.push_back(u);
ver[u].adjacent.push_back(v);
dfs(v, u, ver[v].disjoint_index);
disjoint_counter[v] += disjoint_counter[u];
}
if(ver[s].disjoint_index == ver[e].disjoint_index)
return;
}
}
void dfs(int parent, int v, int d)
{
ver[v].disjoint_index = d;
for(int i = 0; i < ver[v].adjacent.size(); i++)
{
if(ver[v].adjacent[i] == parent)
continue;
dfs(v, ver[v].adjacent[i], d);
}
}
这里可以跳过kiss,只是一个函数,返回两个顶点,表示u和v之间有一条边。
disjoint_counter[i] 显示连接组 i 中有多少个顶点。
在构建这棵树之后,我会找到一条带有简单 dfs 的路径。时间限制是 1 秒,我在某些测试用例上得到了 Time Limit Exceeded。
编辑:内存有限,所以我无法保存所有边缘。 我可以使用的最大内存是 32MB。
【问题讨论】:
-
您能否解释一下为什么需要构建一棵树才能找到两个顶点之间的路径? BFS 有什么问题?
-
有 10 000 000 条边,它们是完全随机的,所以我每次都必须重新运行 for 循环以找到每个顶点的相邻顶点,更糟糕的情况是,它需要 100 000 次,即比我目前的算法慢得多。
-
你说边缘是随机的是什么意思?图中没有给出边吗?
-
当我调用kiss函数时,它给了我2个顶点,它们之间有一条边。对不起,我忘了说我的记忆力有限,我不能保存所有的边缘。
标签: c++ graph tree depth-first-search