看着巨巨们越来越牛逼,渣渣表示,只能做渣渣了、、 整个暑假,就是不停地擦手机屏幕,微博,空间,贴吧,朋友圈,一刷就是一天了,轮流刷,花式刷,刷刷刷、、
距离上一篇博文,好久好久了吧,今天来写一篇水的,算是交差了、、=。=
floyd算法的核心就是dp,对图中的对在 i 和 j 之间的所有其他点进行一次松弛。所以时间复杂度为O(n^3)。对于稠密图,效率高于dijkstra。(主要用于初始化吧、)
核心代码如下,你也许会说,才三个for,so easy 啊,但是到应用的时候,也会稍微复杂一点。这也是我学的第一个最短路算法,现在看来没有当初认为的那么简单了、、
for(int k = 1; k <= n; k ++)
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= n; j ++)
dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
相关应用 : 有向图: ①求任意2点间最短路径 ②求最小环(可判断负圈,检查dis[i][i]) ③求传递闭包
无向图:(无负权边): ①求任意2点间最短路径 ②求最小环
下面就来几道题目好了
HDU 3631 Shortest Path (普通的应用) http://acm.hdu.edu.cn/showproblem.php?pid=3631
该题算是floyd算法的一个应用了吧,但和模版差不多。。 就是当q 操作的时候,只有当mark 过,才可以加入floyd 的过程中,如果没有mark过,就当做不存在这个点。另外需要注意的是,该题是有向图,一开始模版的无向图直接代进去,错了好多次、、、其实该题的思路很清晰、、、
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define INF 1<<29
#define N 310
bool mark[N]; // 标记是否被询问过
int dis[N][N];
int n, m, q;
void floyd(int k) // 此题中,只有当加入k 这个点时,才算是图中有这个点,不然即使输入过也没用
{
for(int i = 0; i < n; i ++)
for(int j = 0; j < n; j ++)
dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
}
void init(int n)
{
int i, j;
for(i = 0; i < n; i ++)
for(j = 0; j < n; j ++)
dis[i][j] = (i == j) ? 0 : INF; // 从一个点到本身的距离是0,否则初始化的时候,设为无限大,代表这两点不连通
}
int main()
{
int u, v, w;
int icase = 1;
while(~scanf("%d%d%d",&n, &m, &q))
{
if(n == 0 && m == 0 && q == 0)
break;
memset(mark, 0, sizeof(mark));
init(n);
for(int i = 1; i <= m; i ++)
{
scanf("%d%d%d",&u, &v, &w);
if(w < dis[u][v])
dis[u][v] = w;
}
int t, a, b;
if(icase > 1) // 虽然这不是重点,但是对于害怕 PE 的coder 来说,也需要注意以下、、
printf("\n");
printf("Case %d:\n", icase ++);
while(q --)
{
scanf("%d",&t);
if(t == 0)
{
scanf("%d",&a);
if(mark[a] == 1)
{
printf("ERROR! At point %d\n",a);
continue;
}
mark[a] = 1;
floyd(a);
}
else
{
scanf("%d %d",&a, &b);
if(!mark[a] || (!mark[b]))
printf("ERROR! At path %d to %d\n",a, b);
else if(dis[a][b] == INF)
printf("No such path\n");
else
printf("%d\n",dis[a][b]);
}
}
}
return 0;
}
HDU 1599 find the mincost route (求无向图的最小环 ) http://acm.hdu.edu.cn/showproblem.php?pid=1599
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define INF 1<<29
#define N 105
int mat[N][N],dis[N][N];
int minloop;
void floyd(int n)
{
int i, j, k;
for(k = 1;k <= n; k ++)
{
for(i = 1; i <= n; i ++)
for(j = 1; j <= n; j ++)
if(i!=j && i!=k && j!=k && dis[i][j] + mat[j][k] + mat[k][i] < minloop)
minloop = dis[i][j] + mat[j][k] + mat[k][i];
for(i = 1; i <= n; i ++)
for(j = 1; j <= n; j ++)
dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
}
}
void init(int n)
{
int i, j;
minloop = INF;
for(i = 1; i <= n; i ++)
for(j = 1; j <= n; j ++)
mat[i][j] = mat[j][i] = dis[i][j] = dis[j][i] = INF;
}
int main()
{
int i,n,m,u,v,w;
while(~scanf("%d%d",&n,&m))
{
init(n);
for(i = 1; i <= m; i ++)
{
scanf("%d%d%d",&u, &v, &w);
if(w < mat[u][v])
mat[u][v] = mat[v][u] = dis[u][v] = dis[v][u] = w;
}
floyd(n);
if(minloop == INF)
printf("It's impossible.\n");
else
printf("%d\n",minloop);
}
return 0;
}