SPFA判负环|BFS|DFS
2015-11-05 07:33
323 查看
判断给定的有向图中是否存在负环。
利用 spfa 算法判断负环有两种方法:
1) spfa 的 dfs 形式,判断条件是存在一点在一条路径上出现多次。
2) spfa 的 bfs 形式,判断条件是存在一点入队次数大于总顶点数。
代码如下:
法 1 (spfa 的 dfs 形式):
法 2 (spfa 的 bfs 形式):
利用 spfa 算法判断负环有两种方法:
1) spfa 的 dfs 形式,判断条件是存在一点在一条路径上出现多次。
2) spfa 的 bfs 形式,判断条件是存在一点入队次数大于总顶点数。
代码如下:
法 1 (spfa 的 dfs 形式):
<span style="background-color: rgb(255, 255, 255);">#include <iostream> #include <cstdio> #include <cstring> using namespace std; const int oo = 1 << 30; const int maxn = 1010; struct Edge { int u, v, t, next; }edge[2010]; int prev[maxn], p[maxn], d[maxn]; bool vis[maxn], flag; int tot; void addEdge(int u, int v, int t) { edge[tot].u = u; edge[tot].v = v; edge[tot].t = t; edge[tot].next = prev[u]; prev[u] = tot ++; } void spfa(int u) { int v; for (int i = prev[u]; i != -1; i = edge[i].next) { v = edge[i].v; if (d[u] + edge[i].t < d[v]) { if (vis[v]) { //存在一点在一条路径上出现多次 flag = true; return ; } else { d[v] = d[u] + edge[i].t; vis[v] = true; spfa(v); } } } } int main() { //freopen("input.txt", "r", stdin); //freopen("output.txt", "w", stdout); int T; int a, b, t; int n, m; scanf("%d", &T); while (T --) { scanf("%d%d", &n, &m); memset(prev, -1, sizeof(prev)); tot = 0; for (int i = 1; i <= m; i ++) { scanf("%d%d%d", &a, &b, &t); addEdge(a, b, t); } memset(vis, false, sizeof(vis)); fill(d, d + n, oo); d[0] = 0; flag = false; spfa(0); if (flag) printf("possible\n"); else printf("not possible\n"); } return 0; }</span>
法 2 (spfa 的 bfs 形式):
<span style="background-color: rgb(255, 255, 255);">#include <iostream> #include <cstdio> #include <cstring> #include <queue> using namespace std; const int oo = 1 << 30; const int maxn = 1010; struct Edge { int u, v, t, next; }edge[2010]; int prev[maxn], p[maxn], d[maxn], in[maxn]; bool vis[maxn]; int tot; queue<int> q; void addEdge(int u, int v, int t) { edge[tot].u = u; edge[tot].v = v; edge[tot].t = t; edge[tot].next = prev[u]; prev[u] = tot ++; } bool spfa(int n) { int u, v; while (!q.empty()) q.pop(); memset(vis, false, sizeof(vis)); memset(in, 0, sizeof(in)); fill(d, d + n, oo); d[0] = 0; vis[0] = true; q.push(0); while (!q.empty()) { u = q.front(); vis[u] = false; for (int i = prev[u]; i != -1; i = edge[i].next) { v = edge[i].v; if (d[u] + edge[i].t < d[v]) { d[v] = d[u] + edge[i].t; if (!vis[v]) { in[v] ++; if (in[v] > n) return true; //存在一点入队次数大于总顶点数 vis[v] = true; q.push(v); } } } vis[u] = false; q.pop(); } return false; } int main() { //freopen("input.txt", "r", stdin); //freopen("output.txt", "w", stdout); int T; int a, b, t; int n, m; scanf("%d", &T); while (T --) { scanf("%d%d", &n, &m); memset(prev, -1, sizeof(prev)); tot = 0; for (int i = 1; i <= m; i ++) { scanf("%d%d%d", &a, &b, &t); addEdge(a, b, t); } if (spfa(n)) printf("possible\n"); else printf("not possible\n"); } return 0; }</span>
相关文章推荐
- ubuntu下eclipse连接手机
- OSChina 周四乱弹 —— 剁手过双十一
- 前端开发调试线上代码的两款工具
- 对比了下Google和百度,差别居然这么大
- 客户端写数据到HDFS
- LeetCode Sliding Window Maximum
- 浅析TCP字节流与UDP数据报的区别
- 浅析TCP字节流与UDP数据报的区别
- [ZT] Vim快捷键分类
- 一个自定义的窗体样式MessageBox控件
- HTTP Keep-Alive模式
- nno_setup制作升级包必须面临的几个问题 2
- LeetCode "Remove Invalid Parentheses"
- 如何运用inno在安装和卸载时提示用户结束进程?
- inno安装卸载时检测程序是否正在运行卸载完成后自动打开网页-代码无效
- Inno Setup 插件大全
- ULK --- Chap3 Processes: Identifying a Process
- INNO安装卸载自动结束进程插件使用
- Inno Setup 在安装程序开始前和卸载程序开始前,检查并关闭运行的进程
- INNO:检测程序是否已经安装,是则弹出卸载提示。