提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
题目概览
现有小a 小b 约定从起点1出发到终点n,中间的路径形成一张n个点 m给边的无向带权联通图。
为了增加路途中的趣味性,小a决定和小b玩一个游戏,他们要轮流指定走到的下一条路,走到终点时轮到谁指定怎么走,谁就输了,小a先走。
因为小a和小b都很聪明,他们只会选择时间花费最小的路去走
一、思路
秉承大胆猜测无需证明(bushi),由题目易得是求从点1到n的单源最短路径(根据时间最小花费可得)
基本上是模板题了,还需要我们实现的是,如何求谁是最终先到终点的那个人?根据题目所给前提:由小a先走,那么最终谁到达终点便是由这条最短路径途径的点的个数所决定
所以解决目标由两个:
1.求点1到n的单源最短路径
2.求点1到n的最短路途径点数
二、算法与代码实现
1.链式前向星
最短路算法的基础是图论+搜索
最短路径实际上就是路径花费的最优解,在实现上采用的是BFS即(Breadth-First Search)广度优先搜索除此之外还需实现的是图(graph)的存储
图的存储有许多方式,邻接表,邻接矩阵等等
我采用的是算法竞赛中被广为使用的--链式前向星
struct Edge{
int to,next,w;
}edge[N];
int head[N];
int tot;
void addedge(int u,int v,int w){
edge[++tot].to=v;
//终点
edge[tot].w=w;
//边权
edge[tot].next=head[u];
//以u为起点上一条边的编号,也就是与这个边起点相同的上一条边的编号
head[u]=tot;
//更新以u为起点上一条边的编号
}
如果说邻接表是不好写但效率好,邻接矩阵是好写但效率低的话,前向星就是一个相对中庸的数据结构。前向星固然好写,但效率并不高。而在优化为链式前向星后,效率也得到了较大的提升。虽然说,世界上对链式前向星的使用并不是很广泛,但在不愿意写复杂的邻接表的情况下,链式前向星也是一个很优秀的数据结构。 ——摘自《百度百科》
2.SPFA
Shortest Path Faster Algorithm
void SPFA(){
memset(dis,INF,sizeof(dis));
memset(vis,0,sizeof(vis));
q.push(1);
vis[1]=1;
dis[1]=0;
while(!q.empty()){
int x=q.front();
q.pop();
vis[x]=0;
for(int i=head[x];i;i=edge[i].next){
int y=edge[i].to,z=edge[i].w;
if(dis[y]>dis[x]+z){
dis[y]=dis[x]+z;
if(!vis[x]) q.push(y),vis[y]=1;
}
}
}
}
我们知道
图中一条路径p=(v0, v1, v2, .....,vn)的权重w(p)是构成该路径所有边的权重之和,满足:
每次边权的更新满足三角不等式性质 与 上界性质(budongbaidu)
总结
比赛时没能完成对最短路 路径数的统计,实际上只需要并查集统计或者反向最短路,将更新命令转换为判断即可,对于上述所讲的数据结构和算法也没有进一步解释,主要还是没什么时间想水篇题解