赶紧补博客,记录一下最短路,健忘(≧﹏ ≦)
1 dijkstra
思路如图:
理解
过程:初始化所有点的dis,使得他们的值无线大,dis即表示到达这点的花费。设置起点的dis为0,让它在第一次挑选的时候被选中。
每次挑选dis最小的点作为当前起点,从当前起点出发,更新从当前起点能到达的所有点的dis。
这样最后更新完所有能到达终点dis值后,取最小的值,就是最短路径。
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long int ll;
const int maxn=1000;//最大顶点数
const int inf=1000000000;//设inf为一个很大的数
int n,m,s,g[maxn][maxn];//n为顶点数,m为边数,s为起点
int d[maxn];//起点到达各点的最短路径长度
bool vis[maxn]={false};//标记数组,vis[i]==true表示已访问,初值均为false
void dijkstra(int s){//s为起点
fill(d,d+maxn,inf);//fill函数将整个d数组赋为inf
d[s]=0;//起点s到达自身的最短距离
for(int i=0;i<n;i++){//循环n次
int u=-1,min1=inf;//u使d[u]最小,min1存放该最小的d[u]
for(int j=0;j<n;j++){//找到未访问的顶中d[]中最小的
if(vis[j]==false&&d[j]<min1){
u=j;
min1=d[j];
}
}
//找不到小于inf的d[u],说明剩下的顶点和起点s不连通
if(u==-1) return;
vis[u]=true;//标记已经访问
for(int v=0;v<n;v++){
//如果v未访问&&u能到达v&&以u为中介点可以使d[v]更优
if(vis[v]==false&&g[u][v]!=inf&&d[u]+g[u][v]<d[v]){
d[v]=d[u]+g[u][v];//优化d[v]
}
}
}
}
int main()
{
int u,v,w;
scanf("%d%d%d",&n,&m,&s);//顶点个数,边数,起点编号
fill(g[0],g[0]+maxn*maxn,inf);//初始化图g
for(int i=0;i<m;i++){
scanf("%d%d%d",&u,&v,&w);//输入u,v以及u->v的边权
g[u][v]=w;
}
dijkstra(s);//dijkstra算法入口
for(int i=0;i<n;i++){
printf("%d ",d[i]);//输出所有顶点的最短距离
}
return 0;
}
/*
6 8 0
0 1 1
0 3 4
0 4 4
1 3 2
2 5 1
3 2 2
3 4 3
4 5 3
*/
dfs代码:
优先级队列优化算法:参考自ChooserZhou
#include<cstdio>
#include<queue>
#include<algorithm>
#define INF 1<<28
#define MAX 300
using namespace std;
int v,e,s;
int graph[MAX][MAX];//图的存储采用邻接矩阵
int dist[MAX];//dist表示当前距源点最短距离,最终为最短距离
bool visit[MAX];//标记为已找出最短路径的点
typedef pair<int,int> P;//用于优先队列中距离与顶点的对应,其中first为距离
void init()//初始化
{
fill(graph[0],graph[0]+MAX*MAX,INF);
fill(dist,dist+MAX,INF);
fill(visit,visit+MAX,false);
}
void Dijkstra(int s)
{
dist[s]=0;
//优先队列
priority_queue <P,vector<P>,greater<P> >que;//最后这两个>中间最好加上空格,防止一些编译器识别错误
que.push(P(0,s));
while(!que.empty())
{
P p=que.top();
que.pop();
int vi=p.second;//vi为当前源点编号
if(visit[vi])
continue;
visit[vi]=true;
for(int i=0;i<v;i++)
{
if(!visit[i]&&dist[i]>dist[vi]+graph[vi][i])//查找vi的相邻顶点
{
dist[i]=dist[vi]+graph[vi][i];
que.push(P(dist[i],i));
}
}
}
}
int main()
{
scanf("%d%d%d",&v,&e,&s);
init();
for(int i=0;i<e;i++)
{
int from,to,cost;
scanf("%d%d%d",&from,&to,&cost);
graph[from][to]=graph[to][from]=cost;
}
Dijkstra(s);
for(int i=0;i<v;i++)
{
printf("%d %d\n",i,dist[i]);
}
return 0;
}
2 floyd
思路:暴力
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int inf=1000000000;//n超过200就出事了
const int maxv=200;//maxv为最大顶点数
int n,m;//n为顶点数,m为边数
int dis[maxv][maxv];//dis[i][j]表示顶点i和顶点j的最短距离
void floyd()
{
for(int k=0;k<n;k++){
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(dis[i][k]!=inf&&dis[k][j]!=inf&&dis[i][k]+dis[k][j]<dis[i][j]){
dis[i][j]=dis[i][k]+dis[k][j];//找到更短的路径
}
}
}
}
}
int main()
{
int u,v,w;
fill(dis[0],dis[0]+maxv*maxv,inf);//dis数组赋初值
scanf("%d%d",&n,&m);//顶点数n,边数m
for(int i=0;i<n;i++){
dis[i][i]=0;//顶点i到顶点i的距离初始化为0
}
for(int i=0;i<m;i++){
scanf("%d%d%d",&u,&v,&w);
dis[u][v]=w;//以有向图为例进行输入
}
floyd();//floyd算法入口
for(int i=0;i<n;i++){//输出dis图
for(int j=0;j<n;j++){
printf("%d ",dis[i][j]);
}
printf("\n");
}
return 0;
}
/*
6 8
0 1 1
0 3 4
0 4 4
1 3 2
2 5 1
3 2 2
3 4 3
4 5 3
*/
3 spfa
思路:
代码: