最短路的Bellman-Ford算法 【判断有无负权环】
来源:互联网 发布:框架户和端口户的返点 编辑:程序博客网 时间:2024/05/17 08:15
Bellman-Ford算法是一种求单源最短路算法,时间复杂度:O(V
过程:
BELLMAN-FORD(G, w, s)1 INITIALIZE-SINGLE-SOURCE(G, s)2 for i ← 1 to |V[G]| - 13 do for each edge (u, v) ∈ E[G]4 do RELAX(u, v, w)5 for each edge (u, v) ∈ E[G]6 do if d[v] > d[u] + w(u, v)7 then return FALSE8 return TRUE
for(节点数-1) // 跟 dijkstra一样 对每条边松弛for(每条边) if(可以松弛) return 存在负边return 无负边
常用一个数组dis[]表示源点到各点距离
结构体{int u; // 起点int v; // 终点int w; // 边权}edge[]表示边的信息
松弛部分很好理解,源点到某一边的终点距离 小于 源点到该边的起点距离 + 起点到终点距离 就更新 到终点距离
if( dis[edge[j].u] + edge[j].w < dis[edge[j].v] ){ dis[edge[j].v] = dis[edge[j].u] + edge[j].w;}
题意:有F个农场(测试数据组数),N个田(节点),M条双向路径(双/无向正权边),W个虫洞(单向负权边),问能否遇见原先的自己(负权环)
这题输入部分
输入F;while(F--){ 输入N,M,W; 1 -> M 加边入图(双向边就当成两条边处理) 1 -> W 负权边入图(注意负权) 进入算法}还可以用标记变量优化,见代码
#include<cstdio>#include<cmath>#include<cstring>#include<iostream>#include<algorithm>using namespace std;#define ll long long#define NMAX 2502#define INF 0x7F7F7F7F#define eps 10^(-6)#define MEM(a) memset(a,0,sizeof(a));#define MEM_MAX(a) memset(a,INF,sizeof(a));#define FOR(i,n) for(int i=0;i<n;i++)#define FIN freopen("in.txt","r",stdin);#define FOUT freopen("out.txt","w",stdout);struct node{ int u,v,w; //边的信息}edge[NMAX*2+201];int dis[NMAX]; //源点到各点距离int N,M,W; //N:节点数,M:正权双向边数,W:负权边数int cnt; //总边数:不等于M+W,因为双向边要算两条边int bellman_ford(int src){ for(int i=1;i<=N;i++) dis[i] = INF; dis[src] = 0; for(int i=1;i<N;i++) { bool flag = false; for(int j=1;j<=cnt-1;j++) { if( dis[edge[j].u] + edge[j].w < dis[edge[j].v] ) { dis[edge[j].v] = dis[edge[j].u] + edge[j].w; flag = true; } } if(!flag) //优化:如果没一条边更新,则最短路完成或有边不可达 break; } for(int i=1;i<=cnt-1;i++) if(dis[edge[i].u] + edge[i].w < dis[edge[i].v]) return 0; return 1;}int main(){ int u,v,w,f,M,W; scanf("%d",&f); while(f--) { cnt = 1; scanf("%d%d%d",&N,&M,&W); for(int i=1;i<=M;i++) { scanf("%d%d%d",&u,&v,&w); edge[cnt].u = u; edge[cnt].v = v; edge[cnt++].w = w; edge[cnt].v = u; edge[cnt].u = v; edge[cnt++].w = w; } for(int i=1;i<=W;i++) { scanf("%d%d%d",&u,&v,&w); edge[cnt].u = u; edge[cnt].v = v; edge[cnt++].w = -w; //负权 } if(bellman_ford(1)) printf("NO\n"); else printf("YES\n"); } return 0;}
此题的spfa解法
#include <cstdio>#include <cstring>#include <string>#include <stack>#include <queue>#include <iostream>#include <algorithm>using namespace std;const int maxn = 505;const int maxm = 2600;const int inf = 0x3f3f3f3f;int inq[maxn], head[maxn], dis[maxn]; //inq[u]==1:u在队列里struct Edge{ int v, w, next;} edge[maxm * 2];int cnt;void add_edge(int u, int v, int w){ //邻接表前插法 edge[cnt].v = v; edge[cnt].w = w; edge[cnt].next = head[u]; head[u] = cnt++;}int times[maxn];void init(int n){ cnt = 0; memset(head, -1, sizeof(head)); memset(inq, 0, sizeof(inq)); memset(dis, inf, sizeof(dis)); memset(times, 0, sizeof(times));}int n;bool spfa(int s, int t){ queue<int>q; q.push(s); dis[s] = 0; inq[s] = 1; times[s]++; while (!q.empty()){ int u = q.front(); q.pop(); inq[u] = 0; for (int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].v; int w = edge[i].w; if (dis[v] > dis[u] + w){ dis[v] = dis[u] + w; if (!inq[v]){ inq[v] = 1; q.push(v); times[v]++; if(times[v] > n){ return false; } } } } } return true;}int main() { int m, a, b, c; int te; cin>>te; int qq; while(te--){ cin >> n >> m>>qq; init(n); for (int i = 0; i < m; ++i){ cin >> a >> b >> c; add_edge(a, b, c); add_edge(b, a, c); } for (int i = 0; i < qq; ++i){ cin >> a >> b >> c; add_edge(a, b, -c); } if(spfa(1, n)) cout<<"NO"<<endl; else cout<<"YES"<<endl; } return 0;}
0 0
- 最短路的Bellman-Ford算法 【判断有无负权环】
- 最短路的bellman-ford算法
- Bellman-ford算法判断有无负环
- bellman ford最短路算法
- 最短路--Bellman-Ford算法
- bellman-ford算法 最短路
- Bellman-ford最短路算法
- poj1860_最短路bellman Ford算法应用
- 最短路之Bellman-Ford算法
- 最短路问题(Bellman-Ford算法)
- 最短路——Bellman-ford算法
- 最短路问题 Bellman-Ford算法
- 最短路算法 Dijkstra Bellman-Ford SPFA
- 最短路——Bellman-Ford算法
- 算法训练 最短路 Bellman-Ford
- 最短路之Bellman-Ford算法
- 最短路算法 Dijkstra Bellman-ford 应用
- C--最短路(Bellman-Ford算法)
- Java transient关键字
- Sublime Text 2 安装 zen coding (Emmet)
- SpringMVC利用return new ModelAndView(new RedirectView("xxx.do"), Map map)重定向传递多参数
- FusionCharts在Java中的基本使用
- Android系统开发(1)——GCC编译器的编译和安装过程
- 最短路的Bellman-Ford算法 【判断有无负权环】
- hdu 4970 树状数组 “改段求段”
- 几何算法学习
- Android LayoutInflater详解
- 实现数组复制
- Hibernate3注解
- hdu 2203亲和串
- scala ActorSyetem异常
- iOS UIWebView键盘处理