殊途同归~

题目:在小米之城,有 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.
在这里插入图片描述
代码如下:

#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];
            }
}
发布了60 篇原创文章 · 获赞 22 · 访问量 6993

猜你喜欢

转载自blog.csdn.net/weixin_43786143/article/details/86706917