【发布时间】:2021-07-26 07:18:18
【问题描述】:
我有一个有向图。最初,假定所有节点都未被访问,vector<int>flag 中的标志为 -1。现在我们从源节点开始并推入 stack<int>s 并生成 flag[source]=0 。现在我进行 DFS 遍历和推送节点 if(flag[node]==-1)& 制作 flag[node]=0。如果访问了所有 DFS 定向链接,我会弹出堆栈的元素并将其标记为flag[s.top()]=1;在推送时,如果我们遇到带有flag[nodes]==0 的节点,则会检测到循环,我会在int final 变量中进行增量;`
你可以在我的代码中看到,我将DFS遍历存储在一个temp向量中,我认为这是垃圾,如何直接通过这些连接的节点来检查标志并检测循环。 目前我的代码可以工作,但无法输入更大的输入。请寻求帮助。
#include<iostream>
#include<vector>
#include<stack>
#include<map>
using namespace std;
int mx=1e5+5;
vector<bool>vist(mx);
vector<vector<int>>Graph(mx);
void dfs(int node,vector<int>&dfs_vec){
vist[node]=true;
dfs_vec.push_back(node);
for(int neigh: Graph[node]){
if(!vist[neigh]){
dfs(neigh,dfs_vec);
}
}
}
//my temp vector is in while loop of main.
int main(){
int num_vertex;int num_edge;
cin>>num_vertex>>num_edge;
int u,v;
for(int i=0;i<num_edge;i++){
cin>>u>>v;
Graph[u].push_back(v);
}
vector<int>flag(num_vertex+1,-1);
stack<int>s;
int source=1;
s.push(source);
flag[source]=0;
int final=0;
while(!s.empty()){
int x=s.top();
vector<int>temp;
dfs(Graph[x][0],temp);
for(auto y:temp){
if(flag[y]==-1){
s.push(y);
flag[y]=0;
}
else if(flag[y]==0){
final++;
}
}
flag[s.top()]=1;
s.pop();
vist.clear();
vist.resize(mx);
}
if(final>0){
std::cout<<"Graph is cyclic";
}
else{
std::cout<<"Graph is not cyclic";
}
}
【问题讨论】:
-
您是否尝试添加一些检查以确保没有向量索引会超出范围?
-
你为什么不直接实现一个已知的算法呢?这看起来效率低下。一方面:为什么要维护一个
final计数器,因为只要找到一个循环就可以退出。找到后无需继续。不是它会消失 ;-) 还有temp向量:你为什么拥有它?为什么不在你的 dfs 遍历中直接使用flag呢? ... 简而言之:您为什么不直接实现几种已知算法中的一种? -
@trincot 先生,非常感谢您的好意建议,是的,我想删除临时向量并在 dfs 遍历中直接传递标志,但我做不到,我请求您请建议我一个代码来做到这一点。谢谢!
-
为您需要的数据设计一个具有属性的类。 dfs 函数成为该类的一个方法,因此它可以访问属性而无需将它们作为参数传入(递归函数会消耗大量堆栈内存,因此您将无法处理大图)。跨度>
-
仅供参考,这里是对设计类以实现图论算法时要考虑的一些问题的简要讨论。 github.com/JamesBremner/PathFinder2/wiki/cGraph-Class-Design
标签: c++ algorithm data-structures graph-theory