最短路径模板 | 理解

赶紧补博客,记录一下最短路,健忘(≧﹏ ≦)

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

思路:

代码:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值