poj 3259 spfa/bellman判断负圈(虫洞)
2015-07-28 20:38
375 查看
题意:判断有向连通图(图中有重边)中是否存在负权环。给定N个点,M条双向正权边,W条单向负权边。
思路:用bellman或者spfa均可。在bellman算法中的表述为:在求出经过了n-1条边的最短路dist[k]之后,再对每条边<u,k>判断一下:加入这条边是否会使得顶点k的最短路径值再缩短,即判断:dist[u]+w(u,k)<dist[k] 是否成立,如果成立,则说明存在从源点可达的负权值回路。
在spfa中的表述为:若一个点最短路被改进的次数达 到n ,则有负权环。
bellman版本:
spfa版本:
思路:用bellman或者spfa均可。在bellman算法中的表述为:在求出经过了n-1条边的最短路dist[k]之后,再对每条边<u,k>判断一下:加入这条边是否会使得顶点k的最短路径值再缩短,即判断:dist[u]+w(u,k)<dist[k] 是否成立,如果成立,则说明存在从源点可达的负权值回路。
在spfa中的表述为:若一个点最短路被改进的次数达 到n ,则有负权环。
bellman版本:
#include <stdio.h> #include <string.h> #define N 522 int T,n,m,w,edgenum; struct edge{ int x,y,w; }e[N*N/2]; int dis ; int bellman_ford(){ int i,j; for(i = 0;i<n-1;i++){ for(j = 0;j<edgenum;j++){ if(dis[e[j].x]+e[j].w < dis[e[j].y]){ dis[e[j].y] = dis[e[j].x]+e[j].w; } } } for(j = 0;j<edgenum;j++){ if(dis[e[j].y] > dis[e[j].x]+e[j].w) return 1; } return 0; } int main(){ //freopen("a.txt","r",stdin); scanf("%d",&T); while(T--){ int i,x,y,len; edgenum = 0; memset(dis,0,sizeof(dis)); scanf("%d %d %d",&n,&m,&w); for(i = 0;i<m;i++){ scanf("%d %d %d",&x,&y,&len); e[edgenum].x = x; e[edgenum].y = y; e[edgenum++].w = len; e[edgenum].x = y; e[edgenum].y = x; e[edgenum++].w = len; } for(i = 0;i<w;i++){ scanf("%d %d %d",&x,&y,&len); e[edgenum].x = x; e[edgenum].y = y; e[edgenum++].w = -len; } if(bellman_ford()) printf("YES\n"); else printf("NO\n"); } return 0; }
spfa版本:
#include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <queue> #include <cstdlib> using namespace std; #define INF 0x3fffffff #define N 1005 struct edge{ int y,next,w; }e[5205]; int first ,top,dis ,num ,used ; int T,n,m,k; queue<int> q; void add(int x,int y,int w){ e[top].y = y; e[top].w = w; e[top].next = first[x]; first[x] = top++; } int relax(int x,int y,int w){ if(dis[y] > dis[x]+w){ dis[y] = dis[x]+w; return 1; } return 0; } int spfa(){ int i,now; q.push(1); for(i = 2;i<=n;i++) dis[i] = INF; dis[1] = 0; memset(num, 0, sizeof(num)); memset(used, 0, sizeof(used)); used[1] = 1; while(!q.empty()){ now = q.front(); q.pop(); used[now] = 0; for(i = first[now];i!=-1;i=e[i].next){ if(relax(now,e[i].y,e[i].w) && !used[e[i].y]){ used[e[i].y] = 1; q.push(e[i].y); num[e[i].y]++; if(num[e[i].y] == n) return 1; } } } return 0; } int main(){ scanf("%d",&T); while(T--){ int i,a,b,w; while(!q.empty()) q.pop(); memset(first, -1, sizeof(first)); top = 0; scanf("%d %d %d",&n,&m,&k); for(i = 1;i<=m;i++){ scanf("%d %d %d",&a,&b,&w); add(a,b,w); add(b,a,w); } for(i = 1;i<=k;i++){ scanf("%d %d %d",&a,&b,&w); add(a,b,-w); } if(spfa()) printf("YES\n"); else printf("NO\n"); } return 0; }
相关文章推荐
- 关于directfb下的inputdriver里的键盘设备
- 在Eclipse上创建Android模拟器
- 33 - 把数组排成最小的数
- LruCache和DiskLruCache与BitmapFun之间的理解
- 大数据的感想
- 1. Java面向对象之泛型-认识泛型
- 名企编程笔试题
- 理解VMware虚拟网络
- 1. Java面向对象之泛型-认识泛型
- iOS学习(frame、bounds、center:)以及UIView的旋转,平移和缩放
- C++错误:不允许使用不完整的类型
- Indeterminate的解决
- iOS property 参数
- 1、代码开发规范。
- HDU5319.Painter
- 快速排序算法
- am335x cotex-A8 数据手册触摸屏章节翻译
- 赋值运算符函数
- 用ant打包可运行的jar文件 (将第三方jar包放进你自己的jar包)
- Java基础之集合函数-Map