蓝桥杯 最短路 By Assassin SPFA算法
来源:互联网 发布:中国癌症发病率 数据 编辑:程序博客网 时间:2024/06/05 06:57
看到题目首先就虎躯一震,不擅长图…
看完题目后感觉的单源最短路径算法就是Dijkstra了吧。下面大概讲一下Dijkstra的思路。
Dijkstra算法讲解有很多,大致的思路就是假设从1点出发,从1出发到达每一个点都有一个距离值(到不了自己定一个较大值替换)。假设当前点为i,已经选择过的点集为G(i已经在G中),那么到达其他一个其他点最小距离,要么是从G中其他点连接(即已经计算过的值),要么是从当前点i过去!然后从未选过的点挑选出G能到达且距离最短的点作为下一个选择的点,依次到结束。因为每一次选择的都是G可达最短的点,所以一定是最优的。具体看Dijkstra其他人的讲解吧。
如果什么都不想直接实现也是可以的,但是无法满分,只能得到80分
#include<bits/stdc++.h>using namespace std;typedef struct node{ int to,value; //to为子节点,value为父亲节点到子节点的距离 }node;vector<node>vec[20002]; //vector建图 int n,m,value;int v[20002]={0},pre[20002]; //v为记录是否到达过,pre记录点i最优解父亲节点是谁 int dis[20002]={0}; //从1到达i的最短长度 const int inf=0x3f3f3f;int main(){ int tmp1,tmp2; node date; scanf("%d%d",&n,&m); for(int t=1;t<=m;t++){ scanf("%d%d%d",&tmp1,&tmp2,&value); date.to=tmp2; date.value=value; vec[tmp1].push_back(date); } for(int i=2;i<=n;i++){ //初始化除了1是0其他全是正无穷 dis[i]=inf; } for(int i=1;i<=n;i++){ //父亲节点初始化全是自己 pre[i]=i; } v[1]=1; int choosepoint=1; //当前节点 for(int i=0;i<vec[choosepoint].size();i++){ //先单独计算从1出发 if(dis[vec[choosepoint][i].to]>vec[choosepoint][i].value+dis[choosepoint]){ dis[vec[choosepoint][i].to]=vec[choosepoint][i].value+dis[choosepoint]; pre[vec[choosepoint][i].to]=choosepoint; //更新子节点的父亲节点,其实在这里不用也无所谓... } } for(int t=1;t<n;t++){ int tmppoint,minvalue=inf; for(int p=1;p<=n;p++){ //找到下一个选择点 if(v[p]==0&&dis[p]<minvalue){ tmppoint=p; } } choosepoint=tmppoint; v[choosepoint]=1; for(int i=0;i<vec[choosepoint].size();i++){ //用下一个节点更新未选过点的距离值 if(dis[vec[choosepoint][i].to]>vec[choosepoint][i].value+dis[choosepoint]){ dis[vec[choosepoint][i].to]=vec[choosepoint][i].value+dis[choosepoint]; pre[vec[choosepoint][i].to]=choosepoint; } } } for(int i=2;i<=n;i++){ cout<<dis[i]<<endl; } return 0;}
但是这里n<=20000,m<=200000数据规模是不行的。查资料有一个SPFA算法,其实就是Dijkstra的优化。
我们再回头看一下Dijkstra的特点,每次更新每个点距离值以后找到最小值,那么我们换一种思路。既然题目中说了没有负数环,那么假定从1出发到当前点i,那么可能通过点i更新后到其他点距离变短,如果每碰到距离变短的点就更新1到其他点距离,再碰到变小的点再更新一直到所有点没有可以松弛的点,是不是就是最优解了?
就相当于Dijkstra每次选择一个点,我保证1到达这个点的距离已经确定了,SPFA算法就是不断更新松弛,不保证当前点值已经是最好,一直在更新出现更小值后更新其他点,直到无点可以松弛就是最优解。
直接看代码吧,很好懂~
#include<bits/stdc++.h>using namespace std;typedef struct node{ int to,value; //to为子节点,value为父亲节点到子节点的距离 }node;vector<node>vec[20002]; //vector建图 int n,m,value;int v[20002]={0}; //v为记录是否在队列之中 int dis[20002]={0}; //从1到达i的最短长度 const int inf=0x3f3f3f; //假定的无穷值 queue<int>que; //SPFA算法中的队列 void SPFA(){ while(!que.empty()){ int now=que.front(); //松弛的当前点 que.pop(); v[now]=0; for(int i=0;i<vec[now].size();i++){ if(v[vec[now][i].to]==0&&dis[vec[now][i].to]>dis[now]+vec[now][i].value){ //如果 队列中不存在且该点被松弛了 que.push(vec[now][i].to); //入队列 dis[vec[now][i].to]=dis[now]+vec[now][i].value; //更新 v[vec[now][i].to]=1; //标记 } } }}int main(){ int tmp1,tmp2; node date; scanf("%d%d",&n,&m); for(int t=1;t<=m;t++){ scanf("%d%d%d",&tmp1,&tmp2,&value); date.to=tmp2; date.value=value; vec[tmp1].push_back(date); } for(int i=2;i<=n;i++){ //初始化除了1是0其他全是正无穷 dis[i]=inf; } que.push(1); v[1]=1; SPFA(); for(int i=2;i<=n;i++){ cout<<dis[i]<<endl; } return 0;}
希望帮助到大家!
0 0
- 蓝桥杯 最短路 By Assassin SPFA算法
- SPFA算法 最短路 蓝桥杯
- 最短路--SPFA算法
- 最短路SPFA算法
- 最短路: SPFA算法
- spfa算法 最短路
- SPFA最短路算法
- 蓝桥杯, 算法训练 最短路 (SPFA)
- 蓝桥杯 - 算法训练 最短路(spfa)
- 蓝桥杯- 最短路(SPFA算法)
- 蓝桥杯 算法训练 最短路 spfa
- 蓝桥杯 算法训练 最短路 (spfa)
- 蓝桥杯算法练习最短路(spfa)
- 蓝桥杯 最短路 spfa
- hdu2544 最短路(SPFA算法)
- 最短路算法(SPFA)
- SPFA算法之最短路。
- 关于最短路算法SPFA
- 对javascript封装,继承的理解
- __init
- 行测-言语错题--中心理解
- Ubuntu16.04+cuda8.0+opencv3.0.0 caffe编译的那些坑
- Git 分布式与集中式
- 蓝桥杯 最短路 By Assassin SPFA算法
- Flashback Database 闪回数据库功能测试
- JSONP跨域访问实现登录验证
- java反射的理解与应用(某大神博客中看到的博文,写的真的太好了,果断转载作为笔记)
- matlab matconvnet的安装配置
- PAT 1015 德才论
- hdoj1106
- Ubuntu 16.04 python3.5安装llvm 3.9.1、llvmlite 0.16.0、numba 0.30.0
- 清除Eclipse中Workspace记录