Floyd算法求无向图最小环
来源:互联网 发布:python 处理get请求 编辑:程序博客网 时间:2024/06/05 18:24
原理可看菊苣博文:http://www.cnblogs.com/khan724/p/4383686.html
自己代码中解释一些小细节。该算法适用于无向图,而有向图的最小环,实际上就是初始化所有点为inf(包括graph[i][i]),然后跑一个普通Floyd即可,寻找最小的graph[i][i]就是最小环。
代码(以POJ-1734为例):
#include <cstdio>using namespace std;const int _inf = 0x7fffffff;const int inf = _inf/3;//程序可能出现3个inf相加const int maxn = 105; int graph[maxn][maxn], pre[maxn][maxn], dis[maxn][maxn];int cnt, path[maxn], sum;int n, m; void init() { for(int i = 1; i <= n; ++i) { for(int j = 1; j <= n; ++j) { pre[i][j] = i; graph[i][j] = dis[i][j] = inf; } graph[i][i] = dis[i][i] = 0; } }void Folyd() { int mins = inf; for(int k = 1; k <= n; ++k) { for(int i = 1; i < k; ++i) for(int j = i+1; j < k; ++j) { //多一个graph数组的作用在于此,在松弛的过程中,会破坏掉两点之间是否真的存在边的表示,所有需要多开一个graph int tmp = dis[i][j] + graph[k][i] + graph[j][k]; //正确写法应该是我这种写法即该环为j,k,i...j,菊苣的写法跟原理不对应,但不会出错,因为是无向图嘛。 if(mins > tmp) { mins = tmp; cnt = 0; sum = 1; int t = i; while(t != j) {path[cnt++] = t;t = pre[j][t];}path[cnt++] = j;path[cnt++] = k; } else if(tmp == mins) ++sum;//求不同的最小环的个数,i,j相同时可根据k区分,相同k可根据i,j区分,所以不会重。 } for(int i = 1; i <= n; ++i) for(int j = 1; j <= n; ++j) { if(dis[i][j] > dis[i][k]+dis[k][j]) { dis[i][j] = dis[i][k]+dis[k][j]; pre[i][j] = pre[k][j]; } } } if(mins == inf) puts("No solution."); else { for(int i = cnt-1; i > 0; --i) printf("%d ", path[i]); printf("%d\n", path[0]); }}int main() { int u, v, w; while(~scanf("%d %d", &n, &m)) { init(); for(int i = 1; i <= m; ++i) { scanf("%d %d %d", &u, &v, &w); if(w < graph[u][v]) { graph[u][v] = graph[v][u] = w; dis[u][v] = dis[v][u] = w; } } Folyd(); } return 0; }
上面的寻路方法是通过pre数组来寻找的,还可以通过nex数组进行寻找,两种寻路方法详情:Floyd 算法求多源最短路径-打印最短路径。
另外解释一下网上经常出现的dfs寻路径的原理,通过一个find数组,find[i][j]表示i到j的最短路最终是通过哪个点松弛得到的。通过find[i][j]的值t再进行find[i][t]和find[t][j]的寻找直到t = 0时,便完成了寻找path上所有的点,最后再加上j和i之间的k点即可。
代码:
#include <cstdio>using namespace std;const int _inf = 0x7fffffff;const int inf = _inf/3;const int maxn = 105; int graph[maxn][maxn], find[maxn][maxn], dis[maxn][maxn];int cnt, path[maxn], sum;int n, m; void init() { for(int i = 1; i <= n; ++i) { for(int j = 1; j <= n; ++j) { find[i][j] = 0; graph[i][j] = dis[i][j] = inf; } graph[i][i] = dis[i][i] = 0; } }void dfs(int i, int j){int k = find[i][j];if(k == 0){path[cnt++] = j;return;}dfs(i, k);dfs(k, j);}void Folyd() { int mins = inf; for(int k = 1; k <= n; ++k) { for(int i = 1; i < k; ++i) for(int j = i+1; j < k; ++j) { int tmp = dis[i][j] + graph[k][i] + graph[j][k]; if(mins > tmp) { mins = tmp; cnt = 0; sum = 1; path[cnt++] = i;dfs(i, j);path[cnt++] = k; } else if(tmp == mins) ++sum; } for(int i = 1; i <= n; ++i) for(int j = 1; j <= n; ++j) { if(dis[i][j] > dis[i][k]+dis[k][j]) { dis[i][j] = dis[i][k]+dis[k][j]; find[i][j] = k; } } } if(mins == inf) puts("No solution."); else { for(int i = cnt-1; i > 0; --i) printf("%d ", path[i]); printf("%d\n", path[0]); }}int main() { int u, v, w; while(~scanf("%d %d", &n, &m)) { init(); for(int i = 1; i <= m; ++i) { scanf("%d %d %d", &u, &v, &w); if(w < graph[u][v]) { graph[u][v] = graph[v][u] = w; dis[u][v] = dis[v][u] = w; } } Folyd(); } return 0; }
晚安_
阅读全文
1 0
- 求无向图最小环算法-floyd
- Floyd算法求无向图最小环
- hdu 1599 (floyd求无向图最小环)
- pku1734求无向图的最小环(Floyd算法扩展)
- 找无向图最小环 floyd算法
- 无向图-最小环-Floyd
- hdu 1599 find the mincost route(找无向图最小环)(floyd求最小环)
- floyd算法求最小环
- Floyd算法求最小环
- 【Floyd求无向图的最小环】PKU-1734-Sightseeing trip
- hdu 1599 find the mincost route(floyd求无向图的最小环)
- hdu1599 find the mincost route(floyd求无向图最小环)
- 无向图最小环算法floy
- hdu 1599find the mincost route(Floyd算法,最小环无向图)
- FZU 2090 无向图最小环 floyd
- BOJ 297 最小环问题 无向图最小环,floyd
- 无向图最小环
- hdu1599求无向图的最小环
- 模拟latch:cbc等待
- Learning of javascript!
- python小练习八——多线程的发布工具
- java[min,max]之间的随机整数
- anaconda 安装opencv后,加载摄像头遇到的问题
- Floyd算法求无向图最小环
- tcp 三次握手和四次挥手【转】
- 网络基础零碎笔记
- HTTP协议
- 强连通分量Kosaraju算法实现
- shell 高级编程(1)
- 自己实现一个泛型LinkedList
- Xmapp启动Tomcat时报Jdk、Jre未安装错误的解决方法
- 事件类型--鼠标与滚轮事件