当前位置: 首页 > 编程日记 > 正文

【HDU/算法】最短路问题 杭电OJ 2544 (Dijkstra,Dijkstra+priority_queue,Floyd,Bellman_ford,SPFA)

最短路径问题是图论中很重要的问题。

解决最短路径几个经典的算法

1、Dijkstra算法

单源最短路径(贪心),还有用 priority_queue 进行优化的 Dijkstra 算法。

2、bellman-ford算法

例题:【ACM】POJ 3259 Wormholes

允许负权边的单源最短路径算法

优点:可以发现负圈。缺点,时间复杂度比Dijkstra算法高。

算法流程:

(1)初始化:将除源点外的所有顶点的最短距离估计值d[v]趋于正无穷,d[start]=0

(2)迭代求解:反复对边集E中的每条边进行松弛操作,使得顶点V中的每个顶点v的最短距离估计值逐步逼近其最短距离(运行|v|-1次)

(3)检验负权回路:判断边集E中的每一条边的两个顶点是否收敛。如果存在未收敛的顶点,则算法返回false,表明问题无解,否则算法返回true,并从源点可达的顶点v的最短距离保存在d[v]中。

Bellman-Ford(G,w,s) :boolean   //图G ,边集 函数 w ,s为源点1        for each vertex v ∈ V(G) do        //初始化 1阶段2            d[v] ←+∞3        d[s] ←0;                             //1阶段结束4        for i=1 to |v|-1 do               //2阶段开始,双重循环。5           for each edge(u,v) ∈E(G) do //边集数组要用到,穷举每条边。6              If d[v]> d[u]+ w(u,v) then      //松弛判断7                 d[v]=d[u]+w(u,v)               //松弛操作   2阶段结束8        for each edge(u,v) ∈E(G) do9            If d[v]> d[u]+ w(u,v) then10            Exit false11    Exit true

3、SPFA

是bellman-ford + 队列优化,其实和bfs关系更密

4、floyd算法

多元最短路算法,是一个经典的动态规划算法

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2544

题目大意是:已知顶点数n,边数及权值,求第1个点到第n个点的最短路的长度

有很多种解法

1、Dijkstra

推荐博客:【算法】【ACM】深入理解Dijkstra算法(单源最短路径算法)

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
const int INF = 9999999;
int map[105][105];
int d[105];
bool vis[105];
int N,M;void dijkstra()
{int i,j,min,pos;for(i=1;i<N;i++){min = INF;for(j=1;j<=N;j++){if(!vis[j] && d[j]<min){min = d[j];pos = j;}}if(min == INF)return ;vis[pos] = true;for(j=1;j<=N;j++){if(!vis[j] && (min+map[pos][j]<d[j])){d[j] = map[pos][j] + min;}}}
}int main()
{int i,j,a,b,t;while(scanf("%d%d",&N,&M)!=EOF){if(N==0 && M==0)return 0;for(i=0;i<=N;i++){for(j=0;j<=N;j++){if(i==j)	map[i][j] = 0;else	map[i][j] = INF;}}for(i=0;i<M;i++){cin >> a >> b >> t;if(t < map[a][b]){map[a][b] = t;map[b][a] = t;}}memset(vis,false,sizeof(vis));for(i=1;i<=N;i++)d[i] = map[1][i];vis[1] =true;dijkstra();cout << d[N] << endl; }return 0;
}

2、Floyd 算法

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn = 9999999;
int map[105][105];int main ()
{int n,m;int a,b,c;int i,j,k;while (scanf("%d%d",&n,&m)!=EOF){if(n==0 && m==0)return 0;for(i=1;i<=n;i++){for(j=1;j<=n;j++){if(i==j)	map[i][j] = 0;else	map[i][j] = maxn;}}for(i=1;i<=m;i++){cin >> a >> b >> c;if(map[a][b] > c){map[a][b] = map[b][a] = c;}}for(k=1;k<=n;k++){for(i=1;i<=n;i++){for(j=1;j<=n;j++){map[i][j] = min(map[i][j],map[i][k]+map[k][j]);}}}cout << map[1][n] << endl;}return 0;
}

3、Dijkstra + 优先队列 (邻接矩阵表示)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <queue>
#include <vector>
#include <functional>
using namespace std;typedef pair<int,int> p;
const int maxn = 9999999;
int N,M;
int d[105];
bool vis[105];
int map[105][105];void dijkstra()
{int i;memset(vis,false,sizeof(vis));memset(d,maxn,sizeof(d));d[1] = 0;priority_queue<p,vector<p>,greater<p> > q;q.push(make_pair(d[1],1));while(q.empty()!=1){p p1=q.top();q.pop();int pos = p1.second;if(vis[pos])continue;vis[pos] = true;for(i=2;i<=N;i++){if(!vis[i] && d[i]>map[pos][i]+d[pos]){d[i] = map[pos][i]+d[pos];q.push(make_pair(d[i],i));}}}
}int main ()
{int i,j;while(scanf("%d%d",&N,&M)!=EOF){if(N==0 && M==0)return 0;for(i=0;i<=N;i++){for(j=0;j<=N;j++){if(i==j)    map[i][j] = 0;else    map[i][j] = maxn;}}int a,b,c;for(i=0;i<M;i++){cin >> a >> b >> c;if(map[a][b] > c){map[a][b] = c;map[b][a] = c;}}dijkstra();cout << d[N] << endl;}return 0;
}

4、Dijkstra + 优先队列 + vector(邻接表表示)

#include <iostream>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <cstdio>
#include <functional>
using namespace std;
typedef pair<int,int> p;//first是最短距离,second是顶点编号
const int maxn = 9999999;struct edge
{int to;//邻接的点int cost;//以及到该点的权值
};vector<edge> eg[105];//邻接表
bool vis[105];//表示是否已经使用过
int d[105];//最短距离
int n,m;//顶点数和边数void dijkstra()
{//priority_queue,优先队列按first由小到大,默认的是从大到小priority_queue<p,vector<p>,greater<p>> q;//初始化memset(d,maxn,sizeof(d));memset(vis,false,sizeof(vis));d[1] = 0;q.push(p(d[1],1));while(q.empty()!=1){p p1 = q.top();q.pop();int pos = p1.second;if(vis[pos])continue;vis[pos] = true;for(int i=0;i<eg[pos].size();i++){edge x = eg[pos][i];if(d[x.to] > d[pos] + x.cost){//起点到x的距离与 选中的这个pos点+pos到x的距离和 作比较d[x.to] = d[pos] + x.cost;q.push(p(d[x.to],x.to));}}}
}int main ()
{while(scanf("%d%d",&n,&m)!=EOF){int i;if(n==0 && m==0)return 0;for(i=1;i<=n;i++)eg[i].clear();int a,b,c;for(i=1;i<=m;i++){cin >> a >> b >> c;edge g1,g2;//无向图的缘故g1.to = b;g1.cost = c;g2.to = a;g2.cost = c;eg[a].push_back(g1);eg[b].push_back(g2);}dijkstra();cout <<d[n] << endl;}return 0;
}

5、bellman_ford(邻接矩阵)

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;const int maxn = 9999999;
int d[105];
int map[105][105];
int n,m;void bellman_ford()
{memset(d,maxn,sizeof(d));d[1] = 0;int flag = 1;int k,i,j;for(k=0;k<n-1 && flag;k++){flag = 0;for(i=1;i<=n;i++){for(j=1;j<=n;j++){if( map[i][j] && d[i]!=maxn && (d[j]>map[i][j]+d[i]) ){d[j] = map[i][j]+d[i];flag = 1;}}}if(flag == 0)return ;}
}int main()
{int i,j;int a,b,c;while(scanf("%d%d",&n,&m)!=EOF){if(n==0 && m==0)return 0;for(i=0;i<=n;i++){for(j=0;j<=n;j++){if(i==j)	map[i][j] = 0;else	map[i][j] = maxn;}}for(i=1;i<=m;i++){cin >> a >> b >> c;if(map[a][b] > c){map[a][b] = c;map[b][a] = c;}}bellman_ford();cout << d[n] << endl;}return 0;
}

用边表示

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;const int maxn = 9999999;typedef struct Edge
{int u,v;int weight;
}Edge;
Edge edge[10000+10]; 
int d[105];
int n,m;void bellman_ford()
{int flag = 1,i,j;for(i=1;i<=n-1 && flag;i++){flag = 0;//因为是无向图,所以是双向的for(j=1;j<=m;j++){if(d[edge[j].v]>d[edge[j].u]+edge[j].weight){d[edge[j].v]=d[edge[j].u]+edge[j].weight;flag = 1;}if(d[edge[j].u]>d[edge[j].v]+edge[j].weight){d[edge[j].u]=d[edge[j].v]+edge[j].weight;flag = 1;}}if(!flag)return ;}
}int main()
{while(scanf("%d%d",&n,&m)!=EOF){if(n==0 && m==0)return 0;memset(d,maxn,sizeof(d));d[1] = 0;for(int i=1;i<=m;i++){cin >> edge[i].u >> edge[i].v >> edge[i].weight;//注意这里设置初始情况if(edge[i].u==1){d[edge[i].v] = edge[i].weight;}}bellman_ford();cout << d[n] << endl;}return 0;
}

6、SPFA(邻接矩阵)因为这个题目不存在负权边,所以就没有记录每个点的入队次数

#include <iostream>
#include <queue>
#include <vector>
#include <cstdio>
#include <cstring>
using namespace std;const int maxn = 9999999;
int n,m;
int map[105][105];
int d[105];
int vis[105];void SPFA()
{memset(vis,false,sizeof(vis));memset(d,maxn,sizeof(d));queue<int> Q;Q.push(1);d[1] = 0;vis[1] = true;int v;while(Q.empty()!=1){int u = Q.front();Q.pop();vis[u] = false;for(v=1;v<=n;v++){if(map[u][v]!=maxn){if(d[u]+map[u][v]<d[v]){d[v] = map[u][v]+d[u];if(!vis[v]){Q.push(v);vis[v] = true;}}}}}
}int main ()
{int i,j;while(scanf("%d%d",&n,&m)!=EOF){if(n==0 && m==0)return 0;for(i=0;i<=n;i++){for(j=0;j<=n;j++){if(i==j)	map[i][j] = 0;else	map[i][j] = maxn;}}int a,b,c;for(i=1;i<=m;i++){cin >> a >> b >> c;if(map[a][b]>c){map[a][b] = c;map[b][a] = c;}}SPFA();cout << d[n] << endl;}return 0;
}

用边来表示

#include <iostream>
#include <queue>
#include <vector>
#include <cstdio>
#include <cstring>
using namespace std;struct Edge
{int s,e,w;Edge(){s = -1;e = -1;w = -1;}
};const int maxn = 9999999;
Edge edge[10000+10];
int n,m;
int d[105];
int vis[105];
int all_e;void SPFA()
{memset(vis,0,sizeof(vis));memset(d,maxn,sizeof(d));d[1] = 0;vis[1] = true;queue<int> Q;Q.push(1);int v;while(Q.empty()!=1){int u = Q.front();Q.pop();vis[u] = false;for(v=0;v<all_e;v++){if(d[edge[v].e]>d[edge[v].s]+edge[v].w){d[edge[v].e]=d[edge[v].s]+edge[v].w;if(!vis[edge[v].e]){Q.push(edge[v].e);vis[edge[v].e] = true;}}}}
}int main ()
{int i;while(scanf("%d%d",&n,&m)!=EOF){if(n==0 && m==0)return 0;all_e = 0;int a,b,c;for(i=0;i<m;i++){cin >> a >> b >> c;edge[all_e].s = a;edge[all_e].e = b;edge[all_e++].w = c;edge[all_e].s = b;edge[all_e].e = a;edge[all_e++].w = c;}SPFA();cout << d[n] << endl;}return 0;
}

相关文章:

javaSE基础知识 1.5整数类型

整数的四种声明类型它们分别是&#xff0c;byte&#xff0c;short&#xff0c;int&#xff0c;long&#xff0c;这四种类型所占用的空间是不同的byte是占用1个字节&#xff0c;它的取值范围是 -128~127&#xff0c;short是占用2个字节&#xff0c;他的取值范围是-32768~32767&a…

源码分析-GLSurfaceView的内部实现

GLSurfaceView类是继承自SurfaceView的&#xff0c;并且实现了SurfaceHolder.Callback2接口。GLSurfaceView内部管理着一个surface&#xff0c;专门负责OpenGL渲染。GLSurfaceView内部通过GLThread和EGLHelper为我们完成了EGL环境渲染和渲染线程的创建及管理&#xff0c;使我们…

【POJ/算法】 3259 Wormholes(Bellman-Ford算法, SPFA ,FLoyd算法)

Bellman-Ford算法 Bellman-Ford算法的优点是可以发现负圈&#xff0c;缺点是时间复杂度比Dijkstra算法高。而SPFA算法是使用队列优化的Bellman-Ford版本&#xff0c;其在时间复杂度和编程难度上都比其他算法有优势。 Bellman-Ford算法流程分为三个阶段&#xff1a; 第一步&am…

进程控制概念简介 多线程上篇(三)

进程控制 进程的基本数据信息是操作系统控制管理进程的数据集合&#xff0c;这些信息就是用来控制进程的&#xff0c;此处我们说的进程控制就是进程的管理。比如进程有状态&#xff0c;那么进程的创建、终止&#xff0c;状态的切换&#xff0c;这都不是进程自主进行的&#xff…

Android OpenGL使用GLSurfaceView预览视频

Android OpenGL使用GLSurfaceView预览视频第一章 相关知识介绍在介绍具体的功能之前&#xff0c;先对一些主要的类和方法进行一些介绍&#xff0c;这样可以更好的理解整个程序1.1 GLSurfaceView在谷歌的官方文档中是这样解释GLSurfaceView的&#xff1a;An implementation of S…

【Android 基础】Animation 动画介绍和实现

转载自&#xff1a;http://www.cnblogs.com/yc-755909659/p/4290114.html1.Animation 动画类型Android的animation由四种类型组成&#xff1a;XML中alph渐变透明度动画效果scale渐变尺寸伸缩动画效果translate画面转换位置移动动画效果rotate画面转移旋转动画效果JavaCode中Alp…

【Codeforces】1111B - Average Superhero Gang Power

http://codeforces.com/problemset/problem/1111/B n 表示要输入的数据的个数 k 最每一个数据最多可以进行多少次操作 m 一共可以进行多少次操作 一次操作&#xff1a;删除这个数&#xff0c;或者给这个数加1 如果n为1的话&#xff0c;那么只要找出m和k的最小值加到那个数…

刷前端面经笔记(七)

1.描述一下渐进增强和优雅降级 优雅降级(graceful degradation)&#xff1a;一开始就构建站点的完整功能&#xff0c;然后针对浏览器测试和修复。渐进增强(progressive enhancement)&#xff1a;一开始只构建站点的最少特性&#xff0c;然后不断针对各浏览器追加功能。 2.为什么…

AR资料与连接梳理

AR引擎相关技术 ------------------------------ ARcore&#xff1a;https://developers.google.cn/ar/discover/ ARkit&#xff1a;https://developer.apple.com/arkit/ 以上重点关注&#xff0c;比较新有一些新的功能大家可以自行体验。 ARToolkithttp://www.artoolkit.orght…

Queues 队列

1. Definiation What is a queue? A queue is a list. With a queue, inseration is done at one end (known as rear) whereas deletion is performed at the other end (known as front). 2. Operations 指针对列 无法自定义队长 // array queue #include<iostream> u…

【HDU】1005 Number Sequence (有点可爱)

http://acm.hdu.edu.cn/showproblem.php?pid1005 A number sequence is defined as follows: f(1) 1, f(2) 1, f(n) (A * f(n - 1) B * f(n - 2)) mod 7. Given A, B, and n, you are to calculate the value of f(n). 直接递归求解f(n)的话&#xff0c;会MLE 在计算…

CNCF案例研究:奇虎360

公司&#xff1a;奇虎360地点&#xff1a;中国北京行业&#xff1a;计算机软件 挑战 中国软件巨头奇虎360科技的搜索部门&#xff0c;so.com是中国第二大搜索引擎&#xff0c;市场份额超过35&#xff05;。该公司一直在使用传统的手动操作来部署环境&#xff0c;随着项目数量的…

C#代码实现对Windows凭据的管理

今天有个任务&#xff0c;那就是使用C#代码实现对windows凭据管理的操作。例如&#xff1a;向windows凭据管理中添加凭据、删除凭据以及查询凭据等功能。于是乎&#xff0c;就开始在网上查找。经过漫长的查询路&#xff0c;终于在一片英文博客中找到了相关代码。经过实验&#…

Android:JNI 与 NDK到底是什么

前言 在Android开发中&#xff0c;使用 NDK开发的需求正逐渐增大但很多人却搞不懂 JNI 与 NDK 到底是怎么回事今天&#xff0c;我将先介绍JNI 与 NDK & 之间的区别&#xff0c;手把手进行 NDK的使用教学&#xff0c;希望你们会喜欢 目录 1. JNI介绍 1.1 简介 定义&…

【ACM】LightOJ - 1008 Fibsieve`s Fantabulous Birthday (找规律,找...)

https://vjudge.net/problem/LightOJ-1008 题目很好理解&#xff0c;第一行表示测试样例的个数&#xff0c;接下来输入一个大于等于1的数&#xff0c;按照格式输出这个数的坐标 蓝色的是 奇数的平方&#xff1b; 红色的是 偶数的平方&#xff1b; 黄色的是对角线&#xff1a…

Computed property XXX was assigned to but it has no setter

报错视图&#xff1a; 原因&#xff1a; 组件中v-model“XXX”&#xff0c;而XXX是vuex state中的某个变量vuex中是单项流&#xff0c;v-model是vue中的双向绑定&#xff0c;但是在computed中只通过get获取参数值&#xff0c;没有set无法改变参数值解决方法&#xff1a; 1.在co…

OpenGL 矩阵变换

origin refer :http://www.songho.ca/opengl/gl_transform.html#modelviewOpenGL 矩阵变换Related Topics: OpenGL Pipeline, OpenGL Projection Matrix, OpenGL Matrix Class Download: matrixModelView.zip, matrixProjection.zipOverviewOpenGL Transform MatrixExample: GL…

2016.8.11 DataTable合并及排除重复方法

合并&#xff1a; DataTable prosxxx; DataTable pstaryyy; //将两张DataTable合成一张 foreach (DataRow dr in pstar.Rows) { pros.ImportRow(dr); } DataTable设置主键&#xff0c;并判断重复 DataTable allpros xxx; 单列设为主键&#xff1a; //设置第某列为主键 allpros.…

【ACM】LightOJ - 1010 Knights in Chessboard(不是搜索...)

https://vjudge.net/problem/LightOJ-1010 给定一个mn的棋盘&#xff0c;你想把棋子放在哪里。你必须找到棋盘上最多可以放置的骑士数量&#xff0c;这样就不会有两个骑士互相攻击。不熟悉棋手的注意&#xff0c;棋手可以在棋盘上攻击8个位置&#xff0c;如下图所示。 不论输入…

webpack-dev-server 和webapck --watch的区别

webpack-dev-server 和webapck --watch 都可以监测到代码变化 &#xff0c; 区别是&#xff1a;webpack-der-server 监测到代码变化后&#xff0c;浏览器可以看到及时更新的效果&#xff0c;但是并没有自动打包修改的代码&#xff1b; webpack --watch 在监测到代码变化后自动打…

Android 应用进行性能分析/APP/系统性能分析

如何对 Android 应用进行性能分析记录一下自己在使用DDMS的过程&#xff1a;开启AS&#xff0c;打开并运行项目 找到TOOL/选择Android Device Monitor一款 App 流畅与否安装在自己的真机里&#xff0c;玩几天就能有个大概的感性认识。不过通过专业的分析工具可以使我们更好的分…

公钥与私钥,HTTPS详解

1.公钥与私钥原理1)鲍勃有两把钥匙&#xff0c;一把是公钥&#xff0c;另一把是私钥2)鲍勃把公钥送给他的朋友们----帕蒂、道格、苏珊----每人一把。3)苏珊要给鲍勃写一封保密的信。她写完后用鲍勃的公钥加密&#xff0c;就可以达到保密的效果。4)鲍勃收信后&#xff0c;用私钥…

【ACM】杭电OJ 4704 Sum (隔板原理+组合数求和公式+费马小定理+快速幂)

http://acm.hdu.edu.cn/showproblem.php?pid4704 1.隔板原理 1~N有N个元素&#xff0c;每个元素代表一个1.分成K个数&#xff0c;即在(N-1)个空挡里放置&#xff08;K-1&#xff09;块隔板 即求组合数C(N-1,0)C(N-1,1)...C(N-1&#xff0c;N-1) 2.组合数求和公式 C(n,0)C(…

Vue 中 CSS 动画原理

下面这段代码&#xff0c;是点击按钮实现hello world显示与隐藏 <div id"root"><div v-if"show">hello world</div><button click"handleClick">按钮</button> </div> let vm new Vue({el: #root,data: {s…

【ACM】UVA - 340 Master-Mind Hints(一定要好好学英语...)

https://vjudge.net/problem/UVA-340 N 表示 密码的个数 第一行是正确的密码 下面的行直到N个0之前&#xff0c;都是猜测的序列&#xff0c;输出的括号&#xff08;A&#xff0c;B&#xff09; A表示对应位置与密码相符合的个数&#xff0c;B表示出现在序列中的数字但是位…

SLAM的前世今生

SLAM的前世 从研究生开始切入到视觉SLAM领域&#xff0c;应用背景为AR中的视觉导航与定位。 定位、定向、测速、授时是人们惆怅千年都未能完全解决的问题&#xff0c;最早的时候&#xff0c;古人只能靠夜观天象和司南来做简单的定向。直至元代&#xff0c;出于对定位的需求&a…

No resource found that matches the given name '@style/Theme.AppCompat.Light'

为什么80%的码农都做不了架构师&#xff1f;>>> Android导入项目时出现此问题的解决办法&#xff1a; 1.查看是否存在此目录&#xff08;D:\android-sdk\extras\android\support\v7\appcompat&#xff09;&#xff0c;若没有此目录&#xff0c;在项目右键Android T…

极限编程 (Extreme Programming) - 迭代计划 (Iterative Planning)

(Source: XP - Iteration Planning) 在每次迭代开始时调用迭代计划会议&#xff0c;以生成该迭代的编程任务计划。每次迭代为1到3周。 客户从发布计划中按照对客户最有价值的顺序选择用户故事进行此次迭代。还选择了要修复的失败验收测试。客户选择的用户故事的估计总计达到上次…

VINS-mono详细解读与实现

VINS-mono详细解读 VINS-mono详细解读 前言 Vins-mono是香港科技大学开源的一个VIO算法&#xff0c;https://github.com/HKUST-Aerial-Robotics/VINS-Mono&#xff0c;是用紧耦合方法实现的&#xff0c;通过单目IMU恢复出尺度&#xff0c;效果非常棒。 感谢他们开源&#x…

mysql+mycat搭建稳定高可用集群,负载均衡,主备复制,读写分离

数据库性能优化普遍采用集群方式&#xff0c;oracle集群软硬件投入昂贵&#xff0c;今天花了一天时间搭建基于mysql的集群环境。 主要思路 简单说&#xff0c;实现mysql主备复制-->利用mycat实现负载均衡。 比较了常用的读写分离方式&#xff0c;推荐mycat&#xff0c;社区活…