题目大意就是,给两个点,在求出最短路径有几条的同时,找一条最短路径上能得到的人最多的路径,输出最短路径数和人数
题目链接 https://pintia.cn/problem-sets/994805342720868352/problems/994805523835109376
然后我对这道题的总结:
1.我们可以认为,求最短路径时想到 深搜广搜;单源多源最短路 ;
2.广搜:可以完成 有权图找两个一开始给定的点的最短路径长,(利用队列)
能做到求解最短路径有几条这个问题,但麻烦
3.深搜:可以完成 有权图找两个一开始给定的点的最短路径长,(利用递归)
也可以求得有几条路径:当然啦,因为深搜就是一种特别暴力的,从头到尾的遍历各种情况,故在求有几种方法时,如果时间复杂度不超的话,就可以选用深搜
4.单源最短路:这道题我觉得有两个地方不能用单源最短路:
1)用邻接矩阵来存储图的话,遍历比较耗时间;但是用前向星或是邻接表的话,就特别麻烦:因为题目给的并不是单线路经,故u v之间有路,v u之间也得有路,着两条路径就都得存下来,就,,,,麻烦
但这也提醒我,如果有的题目:强调是单向路径,而且是稀疏图,就考虑用邻接表 作为图的存储的数据结构。
2)单源最短路径也 能做到求解最短路径有几条这个问题,但麻烦。
5.多元最短路径:由于题目中的起点终点都是一个样例对应固定下来的一组起点终点,故就不用考虑多源最短路了,虽说多源最短路同样能做到求解最短路径有几条这个问题,但麻烦
ac代码
#include <iostream>
#include <string.h>
using namespace std;
int n,m,c1,c2;
int e[505][505];
int renshu[505];
int book[505];
int cnt,maxnum,mindis;
void dfs(int x,int num,int dis)
{
if(x==c2)
{
if(dis<mindis)
{
cnt=1;
maxnum=num;
mindis=dis;
}
else if (dis==mindis)
{
cnt++;
if(num>maxnum)
{
maxnum=num;
}
}
return;
}
for(int i=0;i<n;i++)
{
if(book[i]==0&&e[x][i]!=0x3f3f3f3f)
{
book[i]=1;
dfs(i,num+renshu[i],dis+e[x][i]);
book[i]=0;
}
}
}
int main()
{
int a,b,c;
memset(e,0x3f,sizeof(e));
memset(book,0,sizeof(book));
mindis=0x3f3f3f3f;
cin>>n>>m>>c1>>c2;
for(int i=0;i<n;i++)
{
cin>>renshu[i];
}
for(int i=0;i<m;i++)
{
cin>>a>>b>>c;
e[a][b]=c;
e[b][a]=c;
}
book[c1]=1;
dfs(c1,renshu[c1],0);
cout<<cnt<<" "<<maxnum<<endl;
return 0;
}
这有一篇大佬写的迪杰斯特拉算法的题解,如果用广搜的话思路就应该也一样吧,,,,我还没写,先贴上大佬博客链接
https://blog.csdn.net/adventural/article/details/86708790
如果我写完了就把我的贴上来,,,
一下是我理解的大佬(上面博客链接的那位大佬)的思路,和大佬代码节选
主要思路是:在更新一个点时,会有一个num[ ]数组,if (dist[u]+wei < dist[v]) 那么到 v 点的路径数就可以一更新为与到 u 点的路径数相同 即 num[v] = num[u]; else if (dist[u]+wei == dist[v]) 那么原来到 v 点的路径数还可以保留再加上到 u 点的路径数,两者做和,即为此次更新后的 此时到 v点的路径数。