在微策略和SAP的面试中,都被问及了网络中环路的问题,另外在自己的毕设中也涉及到了此问题。今天小结一下:
网络中的环,一般可以用三种方法进行发现:
1,拓扑排序:
这种方法,比较简单需要存下每个结点的初度、入度;然后选择入度为0的结点进行删除,比较简单。
2,BELLMAN-Ford算法:
这种方法,适用于发现负回路,当然普通网络,我们通过赋权,可以实现转化。但是效率不高。
代码:
for(int i = 1; i < V; i++)
{
for each edge(u,v) in G
do relax(u,v,w);
}
for each edge(u,v) in G
{
if(d[v] > d[u] + w(u,v))
return false;
}
return true;
可参阅http://blog.csdn.net/niushuai666/article/details/6791765
3,深度优先遍历:(微策略的一面,这个居然没有答出来,惭愧)
深度优先,效率较高,需要记录所有结点的访问状态,通过访问状态巧妙地判断是否出现环。
代码:
void dfs()
{
oncycle = -1;
memset(state,0,sizeof(state));//每一个结点的访问状态
for(int i = 0; i< V; i++)
{
pre[i] = -1;
}
for(int i = 0; i< V; i++)
{
if(oncycle != -1)
{
break;
}
if(state[i] == 0)
dfs_visit(i);
}
}
void dfs_visit(int u)
{
if(oncycle != -1)
return;
state[u] = 1;//第一次访问
set<int>::iterator iter = adj[u].begin();
while(iter != adj[u].end()&&oncycle == -1)
{
int j = *iter;
int v = edges[j].v;
if(state[v] == 0)
{
pre[v] = j;
dfs_visit(j);
}else if(state[v] == 1)
{
prev[v] = j;
oncycle = v;
state[u] = 2;
return;//发现环了
}
iter++;
}
state[u] = 2;//所有邻居结点都访问完了
}