关于一个图中是否存在负环
来源:互联网 发布:米惠淘宝返利网 编辑:程序博客网 时间:2024/06/05 23:58
负环的判断
第一次写博客,表示心里很慌,dalao不喜勿喷。
我第一次接触负环的判断是在一道差分约束的题目里:点击打开链接
说实话,这类题目其实都是比较裸的判负环,但是很多人就卡在负环上,有的人会用dijkstra算法(我没有试过,但听学长说判不了,只会算个错的答案出来),有的人用SPFA,但是用的BFS,于是。。。光荣的TLE了,原因就在于在判断以及之后的退出上DFS比BFS更有力,所以要用DFS,那么具体的操作呢?
先来看看正常情况(单源最短路)下的bfs版SPFA:
//h[]初始化为INFvoid SPFA(){ int he=0,t=1;//手写队列,虽然queue很好用,但我还是爱手写 h[st]=0;vis[st]=true; d[1]=st;//d[]就是队列数组 do{//这个循环干啥的应该都懂 he++; int p=d[he]; vis[p]=false; for(register int i=head[p];i!=-1;i=e[i].next)//我建图一般用前向星,vector版的应该是for(int j=0;j<e[sta].size();j++) { int v=e[i].to;//列举下一个节点 if(h[v]>h[p]+e[i].dis)//判断谁更短 { h[v]=h[p]+e[i].dis; if(!vis[v]){//是否访问过该节点 d[++t]=v;//没有则入队 vis[v]=true;//标记 } } } }while(he<t);}那么这种算法在出现了负环的情况下会如何呢?
我们就以这个有点鬼畜的环为例,假设我们搜到了a节点,继续搜b节点,因为边权为负,所以h[a]更新,那么搜b、搜c、搜d时,因为边权都是负的,那么都会更新相应节点的h值,这个时候……我们搜回a节点了,将要发生的一切,似乎就顺理成章了,死循环到天荒地老……那么要如何避免呢?如果你用BFS,那么判定的依据是一个点入队超过n次,这个复杂度足以让你绝望了,但是如果说是DFS,判断的依据就是多次被搜到,这个解决起来就方便多了,看一看代码:
struct node{ int next; int to; int dis;}e[500010];bool vis[500001],flag;//flag标记负环void add(int u,int v,int w){ e[++tot].to=v; e[tot].next=head[u]; e[tot].dis=w; head[u]=tot;}void dfs(int sta){vis[sta]=true;//该点访问过了if (flag)return; for (int i=head[sta];i;i=e[i].next){ int v=e[i].to; if (h[sta]+e[i].dis<h[v]){ h[v]=h[sta]+e[i].dis; if (vis[v]){ flag=true;//重复访问一个点,负环出现,flag改变 return; }else dfs(v);//其实就是把队列改成相应的深搜而已 } }vis[sta]=false;//相当于回溯return ; }//主函数里的调用是for(int i=1;i<=n;i++){dfs(i);if(flag) break;}在这里有一个优化,原版的SPFA的h[]数组初始化时是赋的INF,一个极大的数,这在单源最短路是对的,但在判负环时反而会拖慢效率,所以不如把h[]初始化为0,那么只有出现负权边时才会更新并搜索,在发现负环后立马退出,极大的提升了效率,至于别的快读之类的优化就看你个人了。有关负环我就讲这么多,推荐一些练习:洛谷P1993 P3385 poj3259
本人萌新,dalao不喜勿喷
阅读全文
1 0
- 关于一个图中是否存在负环
- POJ 3259 判断图中是否存在负权回路
- Bellman_ford或spfa 判断图是否存在负环
- POJ 3259 Wormholes (BellmanFord判断图是否存在负环)
- Bellman_ford和SPFA判断是否存在负环
- poj 3259spfa()判断是否存在负环
- bellman-ford算法(判断是否存在负环)
- poj 3259 Wormholes 【spfa判断是否存在负环】
- POJ 3259 Wormholes(SPFA算法判断是否存在负环)
- Wormholes 3259 (最短路+判断负环是否存在)
- POJ 3259 Wormholes 【判断是否存在负环】
- bellman ford 算法 判断是否存在负环
- [模板]poj3259(判断是否存在负环)
- poj 3259 Wormholes (判断图是否存在负圈)
- 判断一个图是否存在环
- 判断一个有向图中是否存在一个环(C++代码)
- 如何判断一个图中是否存在回路
- 如何判断一个图中是否存在回路
- uva 400 Unix ls 127页
- stl容器
- HashMap重要知识点总结
- [LintCode]Anagrams(Python)
- 朴素贝叶斯原理及实现
- 关于一个图中是否存在负环
- python-pandas的基本用法03
- uva 136 120页
- JS利用apply方法,将数组直接当做参数传给函数
- Linux 磁盘加密
- 练习2-3 编写函数 htoi(s),把由十六进制数字组成的字符串(包含可选的前缀0x或0X)转换为与之等价的整型值。字符串中允许包含的数字包括:0~9、a~f以及A~F。
- Curling 2.0
- uva 540 117 页
- kafka使用场景