uva11090Going in Cycle!!(最短路spfa)
来源:互联网 发布:mac怎么升级系统版本 编辑:程序博客网 时间:2024/06/05 00:28
这道题使我彻底弄明白了spfa为什么最多是n-1个点入队,多一个点入队,就证明是有负环必然,举个栗子
比如说读边的顺序呢是这样的1——5,1——2,2——5,2——3,3——5,3——4,4——5,那么1号点先入队列,然后是5号,和2号入队列,1号出队列,5号点出队列,现在队列里只剩2号点,然后把5号和3号入队,5号出队列,然后把与3号相连的且此时不在队列的5,4入队列,3号出队列,然后5号出队列,然后再把与4号相连的5号入队列,这样,5号点进入了4次队列,而且在没有负环的图里最多只能进n-1次队列,即其他的n-1个点都与它相连,并且当时它并未在队列
下面让我们来探讨一下这个题首先这是一道找环的问题,那么我们可以,把所有边都减去一个值,如果出现了负环的情况,则证明,这是一个环,实际上我们减去的这个值,就是我们要求得平均值,这个题用了二分(我也是看了网上的题解才知道用二分的,没办法实在是太菜了),其实这道题用bellman-ford,和floyd找最小环应该都能做,因为只有50个点,另外既然用spfa做了,就需要考虑这个算法所需要考虑的情况,首先就是可能出现1与2相连,3与4相连,4与3相连,正常情况下,我们是找1为起点,然后开始找最短路即可,但是这道题目是找环,那么就会存在不是连通图的情况,实际上最短路也存在,但是不需要考虑,为什么呢,因为给了起点,找起点到其他地方的距离,到不了的根本不用考虑啊。对吧,所以这种情况下,就有两种选择,第一,刚开始把所有点都入队列,过倒是可以过,但是我并没找到初始化的方法,第二种,也就是我现在代码的这种,就是在减去一个值的同时,把所有点扫一遍,看是否能成环,如果可以,则继续进行
还有一点需要考虑的就是减掉的值在spfa找过之后,一定要再给他加回来,要不然原来的数据就被破坏了,无法进行下一组,最后,别忘了double
#include <iostream>#include <stdio.h>#include <queue>#include <string.h>using namespace std;const int INF=0x3f3f3f3f;const int maxn=100;struct Edgenode{ int to,next; double w;};Edgenode edges[maxn*maxn];int n,m;int head[maxn],cnt[maxn],edge;bool vis[maxn];double dis[maxn];void add(int u,int v,double c){ edges[edge].w=c; edges[edge].to=v; edges[edge].next=head[u]; head[u]=edge++;}void init(){ memset(head,-1,sizeof(head)); edge=0;}bool spfa(int y){ queue<int>que; int u; for(int i=0; i<=n; i++) { dis[i]=INF; cnt[i]=0; //vis[i]=0; } dis[y]=0; que.push(y); memset(vis,0,sizeof(vis)); vis[y]=1; while(!que.empty()) { u=que.front(); que.pop(); vis[u]=false; for(int i=head[u]; i!=-1; i=edges[i].next) { int v=edges[i].to; double w=edges[i].w; if(dis[v]>dis[u]+w) { dis[v]=dis[u]+w; if(!vis[v]) { vis[v]=true; que.push(v); if(++cnt[v]>=n) return 0; } } } } return 1;}bool check(double x){ bool flag=0; for(int i=1; i<=n; i++) for(int k=head[i]; k!=-1; k=edges[k].next) edges[k].w-=x; for(int i=1; i<=n; i++) { if(!spfa(i))//这块是把所有点找一遍,看看能否找到环 flag=1; } for(int i=1; i<=n; i++) for(int k=head[i]; k!=-1; k=edges[k].next) { edges[k].w+=x; } return flag;}int main(){ int t,case2=1; int a,b; double w,l=INF*1.0,r=0.0,mid=0.0; cin>>t; while(t--) { init(); //cin>>n>>m; scanf("%d%d",&n,&m); for(int i=1; i<=m; i++) { //cin>>a>>b>>w; scanf("%d%d%lf",&a,&b,&w); add(a,b,w); l=min(l,w); r=max(r,w); } //cout<<m<<endl; printf("Case #%d: ",case2++); //if(m==1) if(!check(r+1))//还有这里就是如果我减掉最大值+1,还是不能构成负环,那么就说明无法成环 printf("No cycle found.\n"); else { double s=1e-8; while(r-l>s) { mid=(r+l)/2.0; if(check(mid)) { r=mid; } else l=mid; } printf("%.2lf\n",r); } } return 0;}
- uva11090Going in Cycle!!(最短路spfa)
- uva11090Going in Cycle!!【bellman二分判负环】
- 最短路(SPFA)
- 最短路 (Spfa)
- 最短路算法(SPFA)
- poj3256(SPFA最短路)
- 最短路(SPFA)算法
- 最短路 - spfa - (一)
- SPFA算法 (最短路)
- HDUOJ_2544(最短路)(SPFA)
- hdu1874(最短路spfa)
- hdu4707Pet最短路(spfa)
- 最短路(SPFA算法)
- 最短路(dijkstra、spfa)
- nyoj1006(最短路次短路spfa)
- UVA 11090 - Going in Cycle!!(最短路`Bellman-Ford)
- Uva 11090 Going in Cycle!!(二分+最短路)
- UVA11090-Going in Cycle!!-最短路/图判环/二分
- 欲望与产品
- ssh框架整合配置
- 欢迎使用CSDN-markdown编辑器
- 深入理解C++的动态绑定和静态绑定
- Ubuntu下安装arm-linux-gnueabi-xxx编译器
- uva11090Going in Cycle!!(最短路spfa)
- iOS———如何申请苹果公司开发者账号流程详细图文介绍(含邓白氏编码的申请方法详细介绍)
- 共享库载入时重定位
- 如何解析sd中的xml文件,并展示
- 归并排序java实现
- extjs表单提交combobox提交值问题
- DeepID2+人脸识别算法学习
- 介绍 RWSH – Ray’s Web SHell (php过狗一句话,过狗菜刀,2016过狗一句话,2016php免杀一句话)
- String,StringBuffer, StringBuilder 的区别是什么?