一、Floyed-Warshall算法

枚举中间点起点终点,对整个图进行松弛操作,就能得到整个图的多源最短路径;

例:POJ2240  Arbitrage

Arbitrage is the use of discrepancies in currency exchange rates to transform one unit of a currency into more than one unit of the same currency. For example, suppose that 1 US Dollar buys 0.5 British pound, 1 British pound buys 10.0 French francs, and 1 French franc buys 0.21 US dollar. Then, by converting currencies, a clever trader can start with 1 US dollar and buy 0.5 * 10.0 * 0.21 = 1.05 US dollars, making a profit of 5 percent. 

Your job is to write a program that takes a list of currency exchange rates as input and then determines whether arbitrage is possible or not. 

Input

The input will contain one or more test cases. Om the first line of each test case there is an integer n (1<=n<=30), representing the number of different currencies. The next n lines each contain the name of one currency. Within a name no spaces will appear. The next line contains one integer m, representing the length of the table to follow. The last m lines each contain the name ci of a source currency, a real number rij which represents the exchange rate from ci to cj and a name cj of the destination currency. Exchanges which do not appear in the table are impossible. 
Test cases are separated from each other by a blank line. Input is terminated by a value of zero (0) for n.

Output

For each test case, print one line telling whether arbitrage is possible or not in the format "Case case: Yes" respectively "Case case: No".

Sample Input

3
USDollar
BritishPound
FrenchFranc
3
USDollar 0.5 BritishPound
BritishPound 10.0 FrenchFranc
FrenchFranc 0.21 USDollar 3
USDollar
BritishPound
FrenchFranc
6
USDollar 0.5 BritishPound
USDollar 4.9 FrenchFranc
BritishPound 10.0 FrenchFranc
BritishPound 1.99 USDollar
FrenchFranc 0.09 BritishPound
FrenchFranc 0.19 USDollar 0

Sample Output

Case 1: Yes
Case 2: No

Source

#include <iostream>
#include <cstdio>
#include <map>
using namespace std;
const int maxn=35;
int n,m;
map<string,int> N;
double dis[maxn][maxn]; int main()
{
int kase=1;
//freopen("Atext.in","r",stdin);
while(cin >> n,n)
{
string a,b;
double tmp;
bool flag=false;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
dis[i][j]=-1;
for(int i=0;i<n;i++){
cin >> a;
N.insert(make_pair(a,i));
}
cin >> m;
for(int i=0;i<m;i++)
{
cin >> a >> tmp >> b;
dis[N[a]][N[b]]=tmp; //邻接矩阵存边的信息;
}
for(int k=0;k<n;k++)
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
if(i!=j&&j!=k&&k!=i&&dis[i][k]!=-1&&dis[k][j]!=-1)
dis[i][j]=max(dis[i][k]*dis[k][j],dis[i][j]);
/*for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
cout << dis[i][j] << " ";
cout << endl;
}
cout << endl;*/
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
if(dis[i][j]*dis[j][i]>1)flag=1;
printf("Case %d: %s\n",kase,flag?"Yes":"No");
N.clear();
kase++;
}
return 0;
}

附:Warshall算法的传递闭包

例:POJ2253  Frogger

Description

Freddy Frog is sitting on a stone in the middle of a lake. Suddenly he notices Fiona Frog who is sitting on another stone. He plans to visit her, but since the water is dirty and full of tourists' sunscreen, he wants to avoid swimming and instead reach her by jumping. 
Unfortunately Fiona's stone is out of his jump range. Therefore Freddy considers to use other stones as intermediate stops and reach her by a sequence of several small jumps. 
To execute a given sequence of jumps, a frog's jump range obviously must be at least as long as the longest jump occuring in the sequence. 
The frog distance (humans also call it minimax distance) between two stones therefore is defined as the minimum necessary jump range over all possible paths between the two stones. 

You are given the coordinates of Freddy's stone, Fiona's stone and all other stones in the lake. Your job is to compute the frog distance between Freddy's and Fiona's stone. 

Input

The input will contain one or more test cases. The first line of each test case will contain the number of stones n (2<=n<=200). The next n lines each contain two integers xi,yi (0 <= xi,yi <= 1000) representing the coordinates of stone #i. Stone #1 is Freddy's stone, stone #2 is Fiona's stone, the other n-2 stones are unoccupied. There's a blank line following each test case. Input is terminated by a value of zero (0) for n.

Output

For each test case, print a line saying "Scenario #x" and a line saying "Frog Distance = y" where x is replaced by the test case number (they are numbered from 1) and y is replaced by the appropriate real number, printed to three decimals. Put a blank line after each test case, even after the last one.

Sample Input

2
0 0
3 4 3
17 4
19 4
18 5 0

Sample Output

Scenario #1
Frog Distance = 5.000 Scenario #2
Frog Distance = 1.414

Source

#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const int maxn=205;
struct node{
int x,y;
}N[maxn];
int con[maxn][maxn],n;
double G[maxn][maxn];
void floyed() //枚举所有边进行松弛;
{
for(int k=0;k<n;k++)
for(int i=0;i<n;i++)
for(int j=0;j<n;j++) //松弛为最大边的最小值;
G[i][j]=min(G[i][j],max(G[i][k],G[k][j]));
}
int main()
{
int kase=0;
while(~scanf("%d",&n),n)
{
for(int i=0;i<n;i++)
scanf("%d%d",&N[i].x,&N[i].y);
for(int i=0;i<n;i++) //这样对称的邻接矩阵只须计算一半
for(int j=i+1;j<n;j++)
G[i][j]=G[j][i]=(double)sqrt(double(N[i].x-N[j].x)*(N[i].x-N[j].x)+double(N[i].y-N[j].y)*(N[i].y-N[j].y));
floyed();
printf("Scenario #%d\n",++kase);
printf("Frog Distance = %.3lf\n\n",G[0][1]);
}
return 0;
}

二、Dijkstra算法

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn=1005;
const int inf=0x3f3f3f3f;
int n;
struct node{
int x,y;
}N[maxn];
bool vis[maxn];
double G[maxn][maxn],d[maxn]; //邻接矩阵
void Dijkstra()
{
fill(vis,vis+n,false);
fill(d,d+n,inf);
d[0]=0;
while(true)
{
int v=-1;
for(int i=0;i<n;i++)
if(!vis[i]&&(v==-1||d[i]<d[v])) //从尚未使用过的顶点中选取一个最小值;
v=i;
if(v==-1)
break;
vis[v]=true;
for(int i=0;i<n;i++)
d[i]=min(d[i],max(d[v],G[v][i])); //源点到各点的最长边的最小值;
}
}
int main()
{
int kase=0;
while(~scanf("%d",&n),n)
{
for(int i=0;i<n;i++)
scanf("%d%d",&N[i].x,&N[i].y);
for(int i=0;i<n;i++) //这样对称的邻接矩阵只须计算一半
for(int j=i+1;j<n;j++)
G[i][j]=G[j][i]=(double)sqrt(double(N[i].x-N[j].x)*(N[i].x-N[j].x)+double(N[i].y-N[j].y)*(N[i].y-N[j].y));
Dijkstra();
printf("Scenario #%d\n",++kase);
printf("Frog Distance = %.3f\n\n",d[1]);
}
return 0;
}

三、Bellman-Ford算法

四、SPFA算法(Shortest Path Faster Algorithm)

队列优化的bellman-ford;

例:POJ1874  畅通工程续

Problem Description
某省自从实行了很多年的畅通工程计划后,终于修建了很多路。不过路多了也不好,每次要从一个城镇到另一个城镇时,都有许多种道路方案可以选择,而某些方案要比另一些方案行走的距离要短很多。这让行人很困扰。

现在,已知起点和终点,请你计算出要从起点到终点,最短需要行走多少距离。
 
Input
本题目包含多组数据,请处理到文件结束。
每组数据第一行包含两个正整数N和M(0<N<200,0<M<1000),分别代表现有城镇的数目和已修建的道路的数目。城镇分别以0~N-1编号。
接下来是M行道路信息。每一行有三个整数A,B,X(0<=A,B<N,A!=B,0<X<10000),表示城镇A和城镇B之间有一条长度为X的双向道路。
再接下一行有两个整数S,T(0<=S,T<N),分别代表起点和终点。
 
Output
对于每组数据,请在一行里输出最短需要行走的距离。如果不存在从S到T的路线,就输出-1.
 
Sample Input
3 3
0 1 1
0 2 3
1 2 1
0 2
3 1
0 1 1
1 2
 
Sample Output
2
-1
 
Author
linle
 
Source
解法1:spfa  2.floyed  3.dijkstra
#include <iostream>
#include <queue>
#include <cstdio>
#include <vector>
using namespace std;
const int maxn=205;
const int inf=0x3f3f3f3f;
typedef pair<int,int> p;
vector<p>E[maxn];//邻接表;
int n,m,d[maxn],inq[maxn]; //d[maxn]到源点的最短距离,inq[maxn]在队列里的元素;
void init()
{
for(int i=0;i<n;i++)E[i].clear();
for(int i=0;i<n;i++)inq[i]=0;
for(int i=0;i<n;i++)d[i]=inf;
}
void spfa(int x)
{
queue<int> que;
que.push(x),d[x]=0,inq[x]=1;
while(!que.empty())
{
int now=que.front();
que.pop();
inq[now]=0;
for(int i=0;i<E[now].size();i++)
{
int v=E[now][i].first;
if(d[v]>d[now]+E[now][i].second)
{
d[v]=d[now]+E[now][i].second;
if(inq[v]==0){
inq[v]=1;
que.push(v);
}
}
}
}
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
init();
int a,b,c;
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&a,&b,&c);
E[a].push_back(p(b,c));
E[b].push_back(p(a,c));
}
scanf("%d%d",&a,&b);
spfa(a);
if(d[b]==inf)
cout << -1 << endl;
else
cout << d[b] << endl;
}
return 0;
}
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=205;
const int inf=0x3f3f3f3f;
int n,m,maze[maxn][maxn]; void floyed()
{
for(int k=0;k<n;k++)
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
if(i!=j&&j!=k&&k!=i)
maze[i][j]=min(maze[i][j],maze[i][k]+maze[k][j]);
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
int a,b,c;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
if(i!=j)
maze[i][j]=inf;
}
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&a,&b,&c);
maze[a][b]=min(c,maze[a][b]);//处理解决重边问题;
maze[b][a]=min(c,maze[b][a]);
}
scanf("%d%d",&a,&b);
floyed();
if(maze[a][b]==inf)
cout << -1 << endl;
else
cout << maze[a][b] <<endl;
}
return 0;
}

//自我整理:最短路径的这三个算法,就像BFS一样;
//spfa:每次把发生更新的点作为当前到该点的最短路径,都入队列视为下一次遍历开始的源点;
//dijkstra:每次只取所有发生更新的点,即所有当前最短路径中里离源点最近的点作为下一次开始的源点,前面的值都视为已确定的最短路径

最短路(Floyed、Dijkstra、Bellman-Ford、SPFA)的更多相关文章

  1. HDOJ 2544 最短路(最短路径 dijkstra算法,SPFA邻接表实现,floyd算法)

    最短路 Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submis ...

  2. 蓝桥杯 algo_5 最短路 (bellman,SPFA)

    问题描述 给定一个n个顶点,m条边的有向图(其中某些边权可能为负,但保证没有负环).请你计算从1号点到其他点的最短路(顶点从1到n编号). 输入格式 第一行两个整数n, m. 接下来的m行,每行有三个 ...

  3. Til the Cows Come Home 最短路Dijkstra+bellman(普通+优化)

    Til the Cows Come Home 最短路Dijkstra+bellman(普通+优化) 贝西在田里,想在农夫约翰叫醒她早上挤奶之前回到谷仓尽可能多地睡一觉.贝西需要她的美梦,所以她想尽快回 ...

  4. hdoj 2544 最短路【dijkstra or spfa】

    最短路 Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submis ...

  5. 【最短路算法】Dijkstra+heap和SPFA的区别

    单源最短路问题(SSSP)常用的算法有Dijkstra,Bellman-Ford,这两个算法进行优化,就有了Dijkstra+heap.SPFA(Shortest Path Faster Algori ...

  6. ACM/ICPC 之 最短路径-Bellman Ford范例(POJ1556-POJ2240)

    两道Bellman Ford解最短路的范例,Bellman Ford只是一种最短路的方法,两道都可以用dijkstra, SPFA做. Bellman Ford解法是将每条边遍历一次,遍历一次所有边可 ...

  7. poj1860 bellman—ford队列优化 Currency Exchange

    Currency Exchange Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 22123   Accepted: 799 ...

  8. Bellman - Ford 算法解决最短路径问题

    Bellman - Ford 算法: 一:基本算法 对于单源最短路径问题,上一篇文章中介绍了 Dijkstra 算法,但是由于 Dijkstra 算法局限于解决非负权的最短路径问题,对于带负权的图就力 ...

  9. uva 558 - Wormholes(Bellman Ford判断负环)

    题目链接:558 - Wormholes 题目大意:给出n和m,表示有n个点,然后给出m条边,然后判断给出的有向图中是否存在负环. 解题思路:利用Bellman Ford算法,若进行第n次松弛时,还能 ...

  10. 最短路计数——Dijkstra

    题目: 给出一个N个顶点M条边的无向无权图,顶点编号为1−N.问从顶点1开始,到其他每个点的最短路有几条. ——传送门 受到题解的启发,用 Dijkstra A掉(手工代码) 思路: 1.无向无权图, ...

随机推荐

  1. 求pi

    参考自:https://www.zhihu.com/question/402311979 由 \[\frac{\pi^4}{90}={\textstyle \sum_{n=1}^{\infty }} ...

  2. 实验4_开源控制器实践——OpenDaylight

    基础要求 需要提交两张图, 一是Mininet拓扑生成并连接控制器的结果 二是Mininet中ping测试截图,并体现个人信息 进阶要求 1.获取拓扑的交换机 2.获取流表状态数量 3.获取指定交换机 ...

  3. Python中的startswith()函数用法

    函数:startswith() 作用:判断字符串是否以指定字符或子字符串开头 一.函数说明语法:string.startswith(str, beg=0,end=len(string))        ...

  4. spring aop切面说明

    execution:处理Join Point的类型,例如call.execution (* android.app.Activity.on**(..)):这个是最重要的表达式,第一个*表示返回值,*表 ...

  5. wx.BoxSizer布局管理器用法,及其Add()方法参数说明

    wx.BoxSizer 布局管理器是一种常见的布局管理器,它可以在水平或垂直方向上布置子窗口部件.同时,它还可以在水平或垂直方向上包含其他 wx.BoxSizer 来创建复杂的布局. 下面是 wx.B ...

  6. java数据类型转换有哪几种?看这篇就够了!

    前言 在上一篇文章中,壹哥给大家讲解了Java中的数据类型,从此大家就知道了基本类型和引用类型,尤其是8种基本类型的使用和各自特点.但实际上数据类型的使用还有很多更深入的内容,比如java数据类型直接 ...

  7. 记一次winfrom 面板改变背景图片

    this.panel1.BackgroundImage = Image.FromFile(@"D:\TestDemo\WindowsFormsApp2\WindowsFormsApp2\黑箭 ...

  8. SpringBoot——定制错误页面及原理

    更多内容,前往 IT-BLOG 一.SpringBoot 默认的错误处理机制 [1]浏览器返回的默认错误页面如下:  ​☞ 浏览器发送请求的请求头信息如下:text/html 会在后面的源码分析中说到 ...

  9. springsecurity-jwt整合

    2 springsecurity-jwt整合 欢迎关注博主公众号「Java大师」, 专注于分享Java领域干货文章http://www.javaman.cn/sb2/jwt 2.1整合springse ...

  10. 【云享专刊】开源遇上华为云,OCP架构变身“云原生框架”

    摘要:华为云DTSE团队出品云原生改造指南,助力轻松实践OCP上云. 本文分享自华为云社区<[云享专刊]开源遇上华为云,OCP架构变身"云原生框架">,作者:华为云社区 ...