最短路问题(Floyd解决)--殊途同归

简介: 最短路问题(Floyd解决)--殊途同归

题目:在小米之城,有 n个小镇(从 1 开始编号),这些小镇通过 m条双向火车铁轨相连,当然某些小镇之间也有公路相连。为了保证每两个小镇之间的人可以方便地互访,市长米小兔就在那些没有铁轨连接的小镇间建造了公路。在两个直接通过公路或铁路相连的小镇之间移动,需要花费 1 小时。火车只能走铁路,汽车只能走公路。


现在有一辆火车和一辆汽车同时从小镇 1 出发,各自前往小镇 n。但是,他们中途不能同时停在同一个小镇(但是可以同时停在小镇 n)。


现在请你来为火车和汽车分别设计一条线路,使火车和汽车尽可能快地到达小镇 n(即要求他们中最后到达小镇 n的时间最短)。


所有的公路或铁路可以被多次使用,求当火车、汽车中各自到达小镇时间最短时,总用时最小的一个。(火车和汽车可以同时到达小镇 n,也可以先后到达。)


这个题目我读了半个小时也没有读懂…(自我嫌弃.jpg)

输入:单组测试数据。


首先有 2 个整数 n和 m(2≤ n≤400,0≤m≤n*(n-1)/2)分别表示小镇的数目和铁轨的数目;


接下来的 m对数字,每对由两个整数 u 和 v 构成,表示小镇 u 和小镇 v之间有一条铁路。(1≤u,v≤n,u!=v)。


输入中保证两个小镇之间最多有一条铁路直接相连。

输出:输出一个整数,表示答案,如果没有合法的路线规划,输出 -1.


23.png

代码如下:

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f  //十六进制无穷大
using namespace std;
const int maxn=450;  
int mp[maxn][maxn]; //存图的二维数组定义在外部
int vis[maxn];
int dis[maxn];
int ans,sum,n,m;
void dij(int v)
{
  int _min,pos=-1;
  memset(vis,0,sizeof(vis));
  for(int i=1;i<=n;i++)
  {
    dis[i]=mp[v][i];
  }
  dis[v]=0;
  vis[v]=1;
  for(int i=1;i<n;i++)
  {
    _min=inf;    //让最小值等于无穷小就可以当最小值比别的值大的时候进行替换
    for(int j=1;j<=n;j++)
    {
      if(!vis[j]&&dis[j]<_min)    //判断:vis那个值非零,并且dis那个值小于最小值
      {
        _min=dis[j];
        pos=j;
      }
    }
    vis[pos]=1;
    for(int j=1;j<=n;j++)
    {
      if(!vis[j]&&dis[j]>dis[pos]+mp[pos][j])
      {
        dis[j]=dis[pos]+mp[pos][j];
      }
    }
  }
}
int main()
{
    scanf("%d%d",&n,&m);
    ans=sum=0;
    if(m==0)
    {
      printf("-1\n");
      return 0;
  }
  else
  {
    memset(mp,inf,sizeof(mp));
    memset(dis,inf,sizeof(dis));
    for(int i=0;i<m;i++)
    {
      int u,v;
      scanf("%d%d",&u,&v);
      mp[u][v]=mp[v][u]=1;
    } 
    dij(1);
    ans=dis[n];
    if(ans==inf||m==(n*(n-1))/2)
    {
      printf("-1\n");
      return 0;
    }
    else
    {
      for(int i=1;i<=n;i++)
      {
        for(int j=1;j<=n;j++)
        {
          if(mp[i][j]==1)
          {
            mp[i][j]=inf;
          }
          else
          {
            mp[i][j]=1;
          }
        }
      }
      dij(1);
      sum=dis[n];
    }
    printf("%d\n",max(sum,ans));
  }
    return 0;
}

总结的来说,做最短路的题要注意这个方面:

1.尽量把初始化语句和算法语句封装成函数;

2.图的顶点和边的个数,以及存图的二维数组,定义在main函数外部;

3.注意是有向图还是无向图;

4.图的点是从1开始计算还是0开始计算;

5.每个测试样例一定要初始化存图的数组。

6.判断最短路存在与否的条件是arr[i][j] 是否等于INF。


Floyd的核心算法:
void floyd()
{
    for(int k = 0 ; k < N ; k++)
        for(int i = 0 ; i < N ; i++)
            for(int j = 0 ; j < N ; j++)
            {
                if(arr[i][k] < INF && arr[k][j] < INF && arr[i][j] > arr[i][k] + arr[k][j])
                    arr[i][j] = arr[i][k] + arr[k][j];
            }
}


相关文章
|
算法 Android开发
LeetCode 周赛上分之旅 #48 一道简单的树上动态规划问题
学习数据结构与算法的关键在于掌握问题背后的算法思维框架,你的思考越抽象,它能覆盖的问题域就越广,理解难度也更复杂。在这个专栏里,小彭与你分享每场 LeetCode 周赛的解题报告,一起体会上分之旅。
71 1
|
算法 Android开发 索引
LeetCode 周赛上分之旅 #44 同余前缀和问题与经典倍增 LCA 算法
学习数据结构与算法的关键在于掌握问题背后的算法思维框架,你的思考越抽象,它能覆盖的问题域就越广,理解难度也更复杂。在这个专栏里,小彭与你分享每场 LeetCode 周赛的解题报告,一起体会上分之旅。
86 0
|
算法 测试技术 Android开发
LeetCode 周赛上分之旅 #45 精妙的 O(lgn) 扫描算法与树上 DP 问题
学习数据结构与算法的关键在于掌握问题背后的算法思维框架,你的思考越抽象,它能覆盖的问题域就越广,理解难度也更复杂。在这个专栏里,小彭与你分享每场 LeetCode 周赛的解题报告,一起体会上分之旅。
77 2
LeetCode 周赛上分之旅 #45 精妙的 O(lgn) 扫描算法与树上 DP 问题
|
算法
二分图的匈牙利算法(用于解决最大匹配问题)--以杭电过山车题为例
二分图的匈牙利算法(用于解决最大匹配问题)--以杭电过山车题为例
122 0
|
算法 测试技术
动态规划真的有那么抽象吗?(递推算法还是动态规划别傻傻分不清了) 以正确的姿势学习动态规划 (入门篇)
动态规划真的有那么抽象吗?(递推算法还是动态规划别傻傻分不清了) 以正确的姿势学习动态规划 (入门篇)
动态规划真的有那么抽象吗?(递推算法还是动态规划别傻傻分不清了) 以正确的姿势学习动态规划 (入门篇)
|
存储 算法
一文足矣——动态规划经典之Floyd(弗洛伊德)算法
一文足矣——动态规划经典之Floyd(弗洛伊德)算法
263 0
一文足矣——动态规划经典之Floyd(弗洛伊德)算法
|
存储 算法 调度
(单源最短路径)一文搞懂dijkstra算法
对于Dijkstra算法,很多人可能感觉熟悉而又陌生,可能大部分人比较了解bfs和dfs,而对dijkstra和floyd算法可能知道大概是图论中的某个算法,但是可能不清楚其中的作用和原理,又或许,你曾经感觉它很难,那么,这个时候正适合你重新认识它。
409 0
(单源最短路径)一文搞懂dijkstra算法
|
C++
这道「岛屿题」用并查集做就体现出其威力了!
之前的岛屿题,用 DFS 和 BFS 来做要比用并查集更加好做并且高效,但是最对这一道题来说,用并查集要更加好做。
108 0
【CCCC】L3-018 森森美图 (30分),计算几何+判断三点共线+bfs最短路
【CCCC】L3-018 森森美图 (30分),计算几何+判断三点共线+bfs最短路
153 0
|
机器学习/深度学习 存储 算法
让你一学就会的那些算法知识总结--基础算法 二分
今天想为大家带来基础算法的一部分也就是二分,我们在实现二分时的核心思想则是:不断地缩小搜索区域,降低查找目标元素的难度。当然,并不是所有的条件都可以使用二分的,所有可以使用二分查找法的题目有以下两个要求,一个是数列有序,另一个是数列使用顺序存储结构。
90 0