• L2-001:dijskstra + 多条最短路径 + 记录中间路径


    题目链接:https://pintia.cn/problem-sets/994805046380707840/problems/994805073643683840
    第一行输出最短路径的条数和能够召集的最多的救援队数量。第二行输出从S到D的路径中经过的城市编号。数字间以空格分隔,输出结尾不能有多余空格。

    思路:

    题意:找最短路径,如果有多条最短路径值相等,找经过的点最多的一条。
    dijkstra算出最短路径,在搜寻最短路时更改一下几点:
    1.记录中间路径节点
    2.更新最短路时,更新点权和,记录当前节点的最短路数量。

    #include<stdio.h>
    #include<string.h>
    #include<math.h>
    #include<algorithm>
    #define inf 0x3f3f3f3f
    using namespace std;
    const int N=555;
    int dis[N];//记录最短距离 
    int path[N];//记录最短路径中间节点 
    int w[N];
    int pathnum[N];//记录最短路径的数目 
    int tol[N];//记录总路径的边权之和 
    int book[N];
    int mp[N][N];//邻接矩阵 
    int n,m,s,d;
    
    void print(int x)//递归输出路径
    {
    	if(path[x]==-1)
    	{
    		printf("%d",x);
    		return ;
    	}
    	print(path[x]);
    	printf(" %d",x);
    	return ;
    }
    
    void dijkstra()
    {
    	memset(book,0,sizeof(book));
    	memset(tol,0,sizeof(tol));
    	int i,j;
    	for(i=0;i<n;i++)
    		dis[i]=inf;
    	dis[s]=0;
    	path[s]=-1;
    	tol[s]=w[s];//对起始点的初始化
    	pathnum[s]=1;//起点的最短路径数为1
    	
    	for(i=0;i<n;i++)
    	{
    		int u,minn=inf;
    		//找到dis路径权值最小的点u 
    		for(j=0;j<n;j++)
    		{
    			if(!book[j]&&dis[j]<minn)
    			{
    				u=j;
    				minn=dis[j];
    			}
    		}
    		book[u]=1;
    		for(j=0;j<n;j++)
    		{
    			//更新最短路径 以u去更新它的邻接点 
    			if(dis[j] > dis[u] + mp[u][j])//松弛时各数组的更新
    			{
    				dis[j] = dis[u] + mp[u][j];//更新最短路径值 ok 
    				path[j] = u;//记录中间路径 ok 
    				tol[j] = tol[u] + w[j]; //更新最短路径对应下的顶点最大值 
    				pathnum[j] = pathnum[u];//如果dis最短路径的值更新为最大值了 说明是第一次更新,并且是用u去更新的v,所以点j的最短路径数量应该等于u的最短路径数量 
    			}
    			else if(dis[j] == dis[u] + mp[u][j])//相等时的更新
    			{
    				pathnum[j] += pathnum[u];//如果最短路径相等了,说明有这两个点的多种方案都可行,应该是二者最短路径的和
    				
    				//在距离相同时 比较所有的点权和 更新为最大的点权 
    				if(tol[j] < tol[u] + w[j])//点权值的更新
    				{
    					tol[j] = tol[u] + w[j];//更新点权值和
    					path[j] = u;//改变中间路径 
    				}
    			}
    		}
    	}
    }
    
    int main()
    {
    	int x,y,z;
    	scanf("%d%d%d%d",&n,&m,&s,&d);
    	for(int i=0;i<n;i++)
    		scanf("%d",&w[i]);
    	memset(mp,inf,sizeof(mp));
    	for(int i=0;i<m;i++)
    	{
    		scanf("%d%d%d",&x,&y,&z);
    		mp[x][y]=z;
    		mp[y][x]=mp[x][y];
    	}
    	dijkstra();
    	printf("%d %d
    ",pathnum[d],tol[d]);
    	print(d);
    	return 0;
    }
    
  • 相关阅读:
    SpringBoot(十):SpringBoot的简单事务管理
    SpringBoot(九):SpringBoot集成Mybatis
    独立式智能扫码插座
    STC-51开发板-单片机控制数码管&按键&点阵综合操作
    单片机定时器与数码管静态显示
    半导体器件
    电路模型与规律
    单片机-引脚并行口结构讲解
    单片机-基础知识,存储原理,引脚简介———(第一个小程序)
    C语言-综合知识点
  • 原文地址:https://www.cnblogs.com/fisherss/p/10422114.html
Copyright © 2020-2023  润新知