• 51Nod 1649-齐头并进(最短路dijkstra)


    在一个叫奥斯汀的城市,有n个小镇(从1到n编号),这些小镇通过m条双向火车铁轨相连。当然某些小镇之间也有公路相连。为了保证每两个小镇之间的人可以方便的相互访问,市长就在那些没有铁轨直接相连的小镇之间建造了公路。在两个直接通过公路或者铁路相连的小镇之间移动,要花费一个小时的时间。

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

    现在请来为火车和汽车分别设计一条线路;所有的公路或者铁路可以被多次使用。使得火车和汽车尽可能快的到达小镇n。即要求他们中最后到达小镇n的时间要最短。输出这个最短时间。(最后火车和汽车可以同时到达小镇n,也可以先后到达。)

    样例解释:

    在样例中,火车可以按照 1⟶3⟶4 行驶,汽车 1⟶2⟶4 按照行驶,经过2小时后他们同时到过小镇4。

    输入

    单组测试数据。
    第一行有两个整数n 和 m (2≤n≤400, 0≤m≤n*(n-1)/2) ,表示小镇的数目和铁轨的数目。
    接下来m行,每行有两个整数u 和 v,表示u和v之间有一条铁路。(1≤u,v≤n, u≠v)。
    输入中保证两个小镇之间最多有一条铁路直接相连。

    输出

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

    数据范围

    对于10%的数据,m=0;
    对于40%的数据,2≤n≤20;
    对于100%的数据,2≤n≤400,0≤m≤n*(n-1)/2;

    输入样例

    4 2
    1 3
    3 4

    输出样例

    2

    题目链接

    题目大意:
    给出n个小镇和m条铁轨,接下来输入m条路,说明彼此之间有铁轨。题目上说的是在城市中有一些公路和铁轨,但是铺设铁轨的地方就不能再有公路了,二者不能重叠,检查是不是火车和汽车都能通过交通路线从1走到n,如果可以则输出后到的最短时间,如果不可以则输出-1。
    解题思路:
    这道题可以用单源最短路去写,题目中虽然没有给出彼此的距离,我们可以假设每条路都是1,然后用1去表示时间。用dijkstra算法去解题,首先输入n和m之后读入地图。注意,这里的地图是铁路的可行地图。然后判断是不是能通过铁路直达1-n,如果能直达则把铁轨的地方变为inf,把inf变为1,求一下汽车的最短时间,如果不能到达则说明汽车能够直达,直接求火车即可(这是题目的第一个坑点,样例的解释不能完全相信,因为在这个小镇中,如果铁路不能从1直达n,就可以直接修一条1-n的公路,使汽车最短时间是1,如果能直达则要改边地图),求得的ans值就是最后要输出的值。AC代码:

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    const int N=450;
    const int inf=0x3f3f3f3f;//一定要够大
    int n,m;
    int mp[N][N],dis[N],book[N];
    int main()
    {
    	ios::sync_with_stdio(false);
    	void dijkstra();
    	cin>>n>>m;
    	for(int i=1;i<=n;i++)
    	  for(int j=1;j<=i;j++)
    	    if(i==j)
    	      mp[i][j]=0;
    	    else
    		  mp[i][j]=mp[j][i]=inf;
    	for(int i=1;i<=m;i++)
    	{
    		int a,b;
    		cin>>a>>b;
    		mp[a][b]=mp[b][a]=1;
    	}
    	if(mp[1][n]==1)//火车能直达则改变地图,因为原来存的是铁轨
    	{
    		for(int i=1;i<=n;i++)
    		  for(int j=1;j<=i;j++)
    		  {
    		  	if(i==j)
    		  	  mp[i][j]=0;
    		    else if(mp[i][j]==1)
    			  mp[i][j]=mp[j][i]=inf;
    			else
    			  mp[i][j]=mp[j][i]=1;
    		  }
    	}
    	for(int i=1;i<=n;i++)
    	  dis[i]=mp[1][i];
    	memset(book,0,sizeof(book));  
    	book[1]=1;
    	dijkstra();
    	if(dis[n]==inf)
    	  cout<<"-1"<<endl;
    	else
    	  cout<<dis[n]<<endl;
    	return 0;
    }
    void dijkstra()
    {
    	int u;
    	for(int i=1;i<=n-1;i++)
    	{
    		int min=inf;
    		for(int j=1;j<=n;j++)
    		{
    			if(!book[j]&&dis[j]<min)
    			{
    				min=dis[j];
    				u=j;
    			}
    		}
    		if(min==inf)//一定要注意这里,因为题目的意思是不一定都能到达的,不加就	RE或WA了。
    	      break;
    		book[u]=1;
    		for(int v=1;v<=n;v++)
    		{
    			if(mp[u][v]<inf)
    			{
    				if(dis[v]>dis[u]+mp[u][v])
    				  dis[v]=dis[u]+mp[u][v];
    			}
    		}
    	}
    }
    
  • 相关阅读:
    日常学习随笔-数组、单链表、双链表三种形式实现队列结构的基本操作(源码注释)
    代码重构之单元测试
    C# yield return 用法与解析
    MVC学习手册之数据注解与验证
    C#数字图像处理算法学习笔记(三)--图像几何变换
    关于变量名与类名同名问题
    C# 计时器
    C#入门--索引器
    C#入门--字段与属性
    var与dynamic
  • 原文地址:https://www.cnblogs.com/Hayasaka/p/14294312.html
Copyright © 2020-2023  润新知