D - Tram(单源最短路径问题)

D - Tram

Tram network in Zagreb consists of a number of intersections and rails connecting some of them. In every intersection there is a switch pointing to the one of the rails going out of the intersection. When the tram enters the intersection it can leave only in the direction the switch is pointing. If the driver wants to go some other way, he/she has to manually change the switch.

When a driver has do drive from intersection A to the intersection B he/she tries to choose the route that will minimize the number of times he/she will have to change the switches manually.

Write a program that will calculate the minimal number of switch changes necessary to travel from intersection A to intersection B.
Input
The first line of the input contains integers N, A and B, separated by a single blank character, 2 <= N <= 100, 1 <= A, B <= N, N is the number of intersections in the network, and intersections are numbered from 1 to N.

Each of the following N lines contain a sequence of integers separated by a single blank character. First number in the i-th line, Ki (0 <= Ki <= N-1), represents the number of rails going out of the i-th intersection. Next Ki numbers represents the intersections directly connected to the i-th intersection.Switch in the i-th intersection is initially pointing in the direction of the first intersection listed.


Output
The first and only line of the output should contain the target minimal number. If there is no route from A to B the line should contain the integer “-1”.


Sample Input
3 2 1
2 2 3
2 3 1
2 1 2
Sample Output
0


题意:给定n个交叉口和起点交叉口和终点交叉口,同样也给出了n个相关交叉口的信息,求起点交叉口到终点交叉口至少需要更换几次开关。

解题思路:这是一个单源最短路径问题,我们按套路做就行。我这里给出两种方法实现。由于数据量较少,Floyd算法并不会超时。


Floyd实现:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<string>
#include<stack>
#include<queue>
#include<cstring>
#include<map>
#include<iterator>
#include<list>
#include<set>
#include<functional>
#include<memory.h>

using namespace std;

int n;//n个站
int a,b;//从a到b
const int maxn=105;
const int inf=0x3f3f3f3f;//表示无穷大。
int dis[maxn][maxn];//表示变更次数。
void floyd(){
	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]);
			}
		}
	}

}
int main(){
	while(cin>>n>>a>>b){
		int t,u;
		memset(dis,inf,sizeof(dis));
		for(int i=1;i<=n;i++){
			cin>>t;
			for(int j=0;j<t;j++){
				cin>>u;
				if(j==0)dis[i][u]=0;
				else dis[i][u]=1;//变更次数。
			}
		}
		floyd();
		if(dis[a][b]==inf)cout<<"-1"<<endl;
		else cout<<dis[a][b]<<endl;
	}
	return 0;
}


Dijkstra实现:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<string>
#include<stack>
#include<queue>
#include<cstring>
#include<map>
#include<iterator>
#include<list>
#include<set>
#include<functional>
#include<memory.h>

using namespace std;

int n;//n个站
int a,b;//从a到b
const int maxn=105;
const int inf=0x3f3f3f3f;//表示无穷大。
int graph[maxn][maxn];//表示变更次数。
int dis[maxn];//dis[i]表示起点到i的最小变更次数。
bool visited[maxn];//判断有没有确定最短路径
void Dijkstra(int s){
	dis[s]=0;
	int minn,pos;
	while(1){
		minn=inf;pos=-1;
		for(int i=1;i<=n;i++){
			if(dis[i]<minn&&!visited[i]){
				minn=dis[i];
				pos=i;
			}
		}
		if(pos==-1)break;
		visited[pos]=true;
		for(int i=1;i<=n;i++){
			if(dis[i]>dis[pos]+graph[pos][i]){
				dis[i]=dis[pos]+graph[pos][i];
			}
		}
	}
}
int main(){
	while(cin>>n>>a>>b){
		int t,u;
		memset(graph,inf,sizeof(graph));
		memset(dis,inf,sizeof(dis));
		memset(visited,false,sizeof(visited));
		for(int i=1;i<=n;i++){
			cin>>t;
			for(int j=0;j<t;j++){
				cin>>u;
				if(j==0)graph[i][u]=0;
				else graph[i][u]=1;//变更次数。
			}
		}
		Dijkstra(a);
		if(dis[b]==inf)cout<<"-1"<<endl;
		else cout<<dis[b]<<endl;
	}
	return 0;
}

posted @   unique_pursuit  阅读(35)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
点击右上角即可分享
微信分享提示