timus1004 最小环()Floyd 算法
通过别人的数据搞了好久才成功,果然还是不够成熟
做题目还是算法不能融会贯通
大意即找出图中至少3个顶点的环,且将环中点按顺序输出
用floyd算法求最小环
因为floyd算法求最短路径是通过中间量k的增加而更新的
算法流程:
对于k,我们知道利用floyd算法求出任意两点i,j最短距离,仅通过路径i-()-j,其中()中的节点编号均<=k-1
可以这样证明:
设最小环上最大点的编号为k0;则当k=k0时,对于任意与k0相接两点i,j两者
1.对于环的剩下一部分必然是i到j的最短路径,因为最佳
2.最短路径必然是通过{1,...,k-1},否则该最小环最大编号必然大于k,故ans=f[i][j]+Graph[i][k]+Graph[j][k] (f[i][j]表示当前通过前k-1点为中间路径的i-j的最短路径)
故通过枚举k,取ans=min(ans,f[i][j]+Graph[i][k]+Graph[j][k]) 其中(i,j<k) 必能找到
而环顺序只需通过计算每次更新f[i][j]时的k记录pre[i][j]=k,之后通过递归即可得到,
需要注意的是:每次更新ans时就要将路径记录下来,不然之后可能路径会更新时被改变,这个改变可不代表路径还会缩短,首先要明白该算法必然能够求出最小环,故若求出最小环后可能之后缩短路径是会重边,即比如i到j的距离通过k后变短了,可是是重边得来的没有意义
#include<iostream>
#include<cstdio>
#include<cstring>
int f[105][105],pre[105][105],Graph[105][105],ans,a[1000];
const int maxn=100000000;
int print(int i,int j){
if (pre[i][j]==0) return 0;
print(i,pre[i][j]);
a[++a[0]]=pre[i][j];
print(pre[i][j],j);
return 0;
}
int main()
{
int i,j,k,l,n,m;
while(1){
scanf("%d",&n);
if (n==-1) break;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++){
f[i][j]=maxn;
Graph[i][j]=f[i][j];
}
memset(pre,0,sizeof(pre));
ans=maxn;
scanf("%d",&m);
for(i=1;i<=m;i++){
scanf("%d%d%d",&j,&k,&l);
if(f[j][k]>l) {f[j][k]=l;Graph[j][k]=l;}
if(f[k][j]>l) {f[k][j]=l;Graph[k][j]=l;}
}
for(k=1;k<=n;k++){
for(i=1;i<=k-1;i++)
for(j=1;j<=k-1;j++)
if(i!=j)
if(ans>f[i][j]+Graph[i][k]+Graph[j][k]){//此处不能用f[][]代替Graph[][] 容易举出实例
ans=f[i][j]+Graph[i][k]+Graph[j][k];
a[0]=0;
a[++a[0]]=i;
print(i,j);
a[++a[0]]=j;
a[++a[0]]=k;
}
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(i!=k&&j!=k&&i!=j)
if(f[i][j]>f[i][k]+f[k][j]){
f[i][j]=f[i][k]+f[k][j];
pre[i][j]=k;
pre[j][i]=k;
}
}
if(ans<maxn){
for(i=1;i<a[0];i++)
printf("%d ",a[i]);
printf("%d\n",a[a[0]]);
}else printf("No solution.\n");
}
return 0;
}
timus1004 最小环()Floyd 算法的更多相关文章
- 图的连通性问题之连通和最小环——Floyd算法
Floyd 判断连通性 d[i][j]仅表示i,j之间是否联通 ;k<=n;k++) ;i<=n;i++) ;j<=n;j++) dis[i][j]=dis[i][j]||(dis[ ...
- floyd算法之最小环问题
最小环问题:都比较容易得到从u 到 v 经过中间某一些结点的最短路,但是我们得确保回来的时候,不能经过那些结点,这样我们就需要改一下floyd算法了 进而我们想到用Floyd算法.我们知道,Floyd ...
- [图论]Floyd 算法小结
Floyd 算法小结 By Wine93 2013.11 1. Floyd算法简介 Floyd算法利用动态规划思想可以求出任意2点间的最短路径,时间复杂度为O(n^3),对于稠密图, 效率要高于执行 ...
- Floyd 算法求多源最短路径
Floyd算法: Floyd算法用来找出每对顶点之间的最短距离,它对图的要求是,既可以是无向图也可以是有向图,边权可以为负,但是不能存在负环(可根据最小环的正负来判定). 基本算法: Floyd算法基 ...
- 温故知新 —— Floyd算法
什么?Floyd?sb O(n ^ 3) 算法早不用了,右上角红叉吧.我之前虽然也认识过 Floyd 算法的重要性,不过多少也是这么想的.然而最近三天连续 rand 到了好几道有关的题目,让我彻底重新 ...
- hdu 1599 find the mincost route (最小环与floyd算法)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1599 find the mincost route Time Limit: 1000/2000 MS ...
- 最小环-Floyd
floyd求最小环 在Floyd的同时,顺便算出最小环. Floyd算法 :k<=n:k++) { :i<k:i++) :j<k:j++) if(d[i][j]+m[i][k]+m[ ...
- 最小环(floyd以及dijkstra实现+例题)
最小环定义 最小环是指在一个图中,有n个节点构成的边权和最小的环(n>=3). 一般来说,最小环分为有向图最小环和无向图最小环. 最小环算法: 直接暴力: 设\(u\)和\(v\)之间有一条边长 ...
- 多源最短路(floyd算法)
Floyd算法: 如何简单方便的求出图中任意两点的最短路径 Floyd-Warshall算法(O(n)比较适用于边较多的稠密图(Dense Graph)) Floyd算法用来找出每对顶点之间的最短距离 ...
随机推荐
- DVDRW光驱无法读DVD刻录盘
原文地址:http://www.douban.com/note/206741292/ 所有的DVD RW驱动器,不能识别DVD ROM光盘问题,都是因为DVD区域没有给定造成的,除非设备损坏!在计算机 ...
- 20145120 《Java程序设计》第1周学习总结
20145120 <Java程序设计>第1周学习总结 教材学习内容总结 刚刚开始学习java,感觉还十分陌生,在第一周的学习中,我知道了java的历史,JVM.JRE和JDK是什么等各种知 ...
- OC的@property 和 @synthesize id
学习java的JDBC,成员变量的setter和getter,eclipse都能帮我们自动生成:当然xcode这款编译器也很强大,也能自动生成: 1:@property @property是写在类的声 ...
- SVN--从本地检出项目至服务器报错--禁止访问
错误描述: 原因:这是访问权限限制引起的. 查看/svn/test目录的权限--之前我修改过的 现在添加一个user就好了--这个添加的developer是我之前导入本地项目时已经验证过的,所以再导入 ...
- 网站常用css必备css reset
在我们写前端代码页面的时候,很多常用的CSS类都是固定的!但没有一个标准或者大家都按自己的方式去随意的写,这样就每次都重复写一些固定的类! 为此HTML5 Doctor(HTML5医生)为我们总结了一 ...
- 使用 Storyboard Segue 实作 UIViewController 的切换
http://blog.csdn.net/mazhen1986/article/details/7791430 Storyboard 是在 iOS 5 SDK 中才出现的新名词,它其实就是原本的 Xi ...
- 前端H5开发工具 Adobe Edge
http://www.cnblogs.com/adobeedge/ http://my.oschina.net/duolus/blog/212801?fromerr=WAcqscJl
- CF 221div2 A. Lever
A. Lever 题目:http://codeforces.com/contest/376/problem/A 题意:杠杆原理 比两边的重量 input =^== output balance 9== ...
- FWT 学习总结
我理解的FWT是在二元运算意义下的卷积 目前比较熟练掌握的集合对称差卷积 对于子集卷积和集合并卷积掌握不是很熟练(挖坑ing) 那么就先来谈一谈集合对称差卷积吧 所谓集合对称差卷积 就是h(i)=si ...
- lintcode:Fibonacci 斐波纳契数列
题目: 斐波纳契数列 查找斐波纳契数列中第 N 个数. 所谓的斐波纳契数列是指: 前2个数是 0 和 1 . 第 i 个数是第 i-1 个数和第i-2 个数的和. 斐波纳契数列的前10个数字是: 0, ...