算法与数据结构实验题 10.24 旅行二——dijkstra算法

算法与数据结构实验题 10.24 旅行二

★实验任务

王尼玛又想出去旅游了,由于王尼玛是个抠门的人,所以王尼玛想要花最少的钱去一个自己想去的地方。王尼玛决定使用火车去旅行,地图上总共有n个城市,其中有k个城市是王尼玛想去玩的城市。由于王尼玛天天为公司加班加点,公司决定奖励他,免费送他去其中的m个城市(也就是说王尼玛能选择这m个城市中的一个作起点)。王尼玛数学不好,让你帮他选一条花费最少的路,这条路最终能到某一个他喜欢的城市。

★数据输入

第一行有四个整数n,T,m和k,表示有n个城市和T条路,公司奖励王尼玛其中m个城市,王尼玛喜欢其中的k个城市。

接下来有T行,每行有三个整数a,b,c,表示a城市和b城市火车通行的花费(火车通行是双向的)

接下来一行有m个整数,表示公司奖励的m个城市的编号。

最后一行有k个整数,表示王尼玛喜欢的k个城市的编号。

(2<=n<=50000,1<=T<=200000, 1<=m,k<=n ,数据保证王尼玛一定能到喜欢的城市)

★数据输出

每个样例输出一行,输出王尼玛能去某个喜欢的城市的最短花费。

输入示例

10 6 2 3
1 3 5
1 4 7
2 8 12
3 8 4
4 9 12
9 10 2
1 2
8 9 10

输出示例

9

求图的某点到终点的最短路径

解法:用dijksta算法

dijkstra算法:

用邻接矩阵存储图

建立dis数组,用来表示各点到起点的距离,初始化为INF

随后,从起点开始,先求出距离起点最近的结点(一开始会通过map来赋值dis,然后通过dis大小来得到这个结点),然后用vis数组标记该结点代表这个结点已经在最短路径之中

记录该节点下标,然后更新各点到起点的距离:dis[该点下标] + map[该点下标][各点下标]

也就是这个点到起点的距离加上这个点到其他点等于其他点到起点的距离

然后重复n次,遍历完n个结点为止;

#include<bits/stdc++.h> 
using namespace std;
#define Inf 0x3f3f3f3f
int n,t,m,k;
int map1[10000][10000];
int dis[50005];
int vis[50005];
int a,b,c;
int road[200005][3];

void crea(){
	memset(map1,Inf,sizeof(map1));
	for(int i = 1;i<=n;i++)
	{
		map1[i][i] = 0;
	}
}
void dijks(int u){
	memset(vis,0,sizeof(vis));
	for(int r = 1;r<=n;r++){
		dis[r] = map1[u][r];
	}
	vis[u] = 1;
	for(int r = 1;r<n;r++){
		int minn = Inf,temp;
		for(int i = 1;i<=n;i++){
			if(!vis[i]&&dis[i]<minn){
				minn = dis[i];
				temp = i;
			}
		}
		vis[temp] = 1;
		for(int i = 1;i<=n;i++){
			if(map1[temp][i]+dis[temp]<dis[i]){
				dis[i] = map1[temp][i]+dis[temp];
			}
		}
	}
}

int main(){
	
	
	cin>>n>>t>>m>>k;
	crea();
	for(int i = 0;i<t;i++)
	{
		cin>>road[i][0]>>road[i][1]>>road[i][2];
		if(map1[road[i][0]][road[i][1]]>road[i][2]){
			map1[road[i][0]][road[i][1]] = road[i][2];
			map1[road[i][1]][road[i][0]] = road[i][2];
		}
	}
	int like[n];
	int start[n];
	for(int i = 0;i<m;i++)
	{
		cin>>start[i];
	}
	for(int i = 0;i<k;i++)
	{
		cin>>like[i];
	}
	int min = Inf;
	for(int i = 0;i<m;i++)
	{
		dijks(start[i]);
		
		for(int j = 0;j<k;j++)
		{
			if(min>dis[like[j]])
			{
				min = dis[like[j]];
			}
		}
		memset(dis,Inf,sizeof(dis));
	}
	cout<<min; 
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值