最短路径

单源最短路径Djikstra算法

题目链接 https://vjudge.net/problem/Aizu-ALDS1_12_B

题目描述:一个有向图G(V,E) 第一行输入节点数n,接下来n行以图的邻接表存储,第一个数为该节点的出度。输出每个顶点和距离。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <stack>
#include <vector>
using namespace std;
#define maxn  10005
#define INF 0x3f3f3f3f 
int n, m[maxn][maxn];
int u, v ,k, c;
int flag[maxn];

void dijkstra() {
    int d[maxn];
    for (int i = 0; i < n; i++) {                      //初始化 
        d[i] = INF;
        flag[i] = 0;
    }

    d[0] = 0;
    while (1) {
        int minv = INF;
        u = -1;
        
        for (int i = 0; i < n; i++) {                  //选出权值最小的边 v加入S 
            if (minv > d[i] && flag[i] == 0) {
                u = i;
                minv = d[i];
            }
        }

        if (u == -1)
            break;

         flag[u] = 1;                                 //标记已经加入S
       
         for (int v = 0; v < n; v++) {                //对V-S中所有顶点的距离值进行修改 
            if (flag[v] == 0 && m[u][v] != INF && d[v] > d[u] + m[u][v]) 
                d[v] = d[u] + m[u][v];
            
        }                                           
       
    }

    for (int i = 0; i < n; i++)
        printf("%d %d\n", i, d[i] == INF ? -1 : d[i]);
}
int main()
{
    scanf("%d", &n);

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            m[i][j] = INF;
        }
    }
    for (int i = 0; i < n; i++) {
        scanf("%d %d", &u, &k);
        for (int j = 0; j < k; j++) {
            scanf("%d %d", &v, &c);
            m[u][v] = c;
        }
    }
    dijkstra();
    return 0;
}

使用优先队列优化Dijkstra算法

输入 顶点总数 6 总边数 9

0 2 4

1 0 2

0 3 28

2 5 8

2 1 15

5 3 13

5 4 18

4 3 4

1 4 10

#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <queue>
#include <vector>
using namespace  std;

typedef long long ll;
typedef pair<int,int> p;

#define M 30005
#define INF 0x3f3f3f3f

struct edge
{
    int v,next,w;
}E[150005];

int head[M];
int d[M];
int n,m,cnt;

priority_queue<p,vector<p>,greater<p> > q;

int init()
{
    cnt=0;
    memset(head,-1,sizeof(head));
    while(!q.empty()){
        q.pop();
    }
}

void addedge(int u,int v,int w)
{
    E[cnt].v=v;E[cnt].w=w;
    E[cnt].next=head[u];
    head[u]=cnt++; 
}

void dijkstra(int s)
{
    for(int i=1;i<=n;i++)
        d[i]=INF;
    d[s]=0;
    q.push(make_pair(d[s],s));
    while(!q.empty()){
        p x=q.top();
        q.pop();
        int u=x.second;
        if(d[u] != x.first) continue;
        for(int e=head[u];e!=-1;e=E[e].next){
            int t=d[u]+E[e].w;
            if(d[E[e].v] > t){
                d[E[e].v] =t;
                q.push(make_pair(t,E[e].v));
            }
        }
    }
}

int main()
{
    scanf("%d%d",&n,&m);
    init();
    for(int i=0;i<m;i++){
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        addedge(u,v,w);
    }
    dijkstra(1);
    for(int i=2;i<=n;i++)
    printf("%d\n",d[i]);
    return 0;
}

这个优化算法自己慢慢体会吧。。

Floyd算法

弗洛伊德算法是解决任意两点间的最短路径的一种算法。

(1)从任意一条单边路径开始。所有两点之间的距离是边的权,如果两点之间没有边相连,则权为无穷大。

(2)对于每一对顶点 u 和 v,看看是否存在一个顶点 w 使得从 u 到 w 再到 v 比已知的路径更短。如果是更新它。

核心代码

typedef int dis[M][M];
typedef int paths[M][M];
void floyd(Mgraph g,paths p,dis d)
{
    int i,j,k;
	for(i=0;i<g.n;i++)
		for(j=0;j<g.n;j++)
		{
			d[i][j]=g.edges[i][j];
			if(i!=j&&d[i][j]<FINITY)
				p[i][j]=i;
			else
				p[i][j]=-1;
		}
		for(k=0;k<g.n;k++)
		{
			for(i=0;i<g.n;i++)
				for(j=0;j<g.n;j++)
					if(d[i][j]>(d[i][k]+d[k][j]))
					{
						d[i][j]=d[i][k]+d[k][j];
						p[i][j]=k;
					}
		}
}

最短路径拓展算法

Bellman - ford算法 : 求含负权图的单源最短路径的一种算法

SPFA 算法:  Bellman-Ford算法 的队列优化算法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值