最短路模板(dijkstra+邻接表)

#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<queue>
#include<math.h>
#include<set>
#include<vector>
using namespace std;
#define maxn 550
#define MM 10000000
int V[maxn];
int d[maxn];
int fa[maxn];
int first[maxn],next[maxn],w[maxn],u[maxn],v[maxn];
int n,m;
void read_()
{                   //单向 or 双向均可~
    scanf("%d%d",&n,&m);
    memset(first,-1,sizeof(first));
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&u[i],&v[i],&w[i]);
        next[i]=first[u[i]];
        first[u[i]]=i;
    }
   //双向路径
    for(int i=m+1;i<=2*m;i++)
    {
        u[i]=v[i-m];
        v[i]=u[i-m];
        w[i]=w[i-m];
        next[i]=first[u[i]];
        first[u[i]]=i;
    }

}
void Dijjkstra()
{
    memset(V,0,sizeof(V));
    memset(fa,0,sizeof(fa));
    for(int i=1;i<=n;i++)
        d[i]=(i==1?0:MM);
    for(int i=1;i<=n;i++)
    {
        int x,mm=MM;
        for(int j=1;j<=n;j++)
            if(d[j]<mm && !V[j])
            mm=d[x=j];
            V[x]=1;
          for(int e=first[x];e!=-1;e=next[e])
          {
              if(d[v[e]]>d[x]+w[e])
              {
                  d[v[e]]=d[x]+w[e];
                  fa[v[e]]=x;
              }

          }
    }
}
void dfs(int x ) //输出路径
{
    cout<<x<<endl;
    if(fa[x]==0)
        return;
    else
  {
        dfs(fa[x]);
        if(x==n)
      cout<<fa[x];
      else
      cout<<fa[x]<<' ';
  }
}
int main()
{
    read_();
    Dijjkstra();
    dfs(n);     //输出路径:可更改终点值。
    cout<<' '<<n<<endl;
   return 0;
}
其他的模板会陆续上传~

转载于:https://www.cnblogs.com/zhanpang/p/5682903.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是使用邻接表实现Dijkstra算法的C语言代码: ```c #include <stdio.h> #include <stdlib.h> #include <limits.h> #define MAX_VERTEX_NUM 100 // 最大顶点数 #define INF INT_MAX // 无穷大 // 边的结构体 typedef struct Edge { int dest; // 目标顶点编号 int weight; // 权重 struct Edge *next; // 下一条边指针 } Edge; // 邻接表中顶点的结构体 typedef struct Vertex { Edge *head; // 第一条边 } Vertex; // 图的结构体 typedef struct Graph { Vertex vertices[MAX_VERTEX_NUM]; // 顶点数组 int vertex_num; // 顶点数 } Graph; // 初始化图 void init_graph(Graph *graph, int vertex_num) { graph->vertex_num = vertex_num; for (int i = 0; i < vertex_num; i++) { graph->vertices[i].head = NULL; } } // 添加边 void add_edge(Graph *graph, int src, int dest, int weight) { Edge *edge = (Edge *) malloc(sizeof(Edge)); edge->dest = dest; edge->weight = weight; edge->next = graph->vertices[src].head; graph->vertices[src].head = edge; } // Dijkstra算法 void dijkstra(Graph *graph, int start, int *dist, int *prev) { int visited[MAX_VERTEX_NUM] = {0}; // 是否已经访问 for (int i = 0; i < graph->vertex_num; i++) { dist[i] = INF; // 到各个顶点的距离都设置为无穷大 prev[i] = -1; // 各个顶点的前驱顶点都设置为-1 } dist[start] = 0; // 起点到自身的距离为0 for (int i = 0; i < graph->vertex_num; i++) { int min_dist = INF; int u = -1; // 找到未访问顶点中距离最近的顶点 for (int j = 0; j < graph->vertex_num; j++) { if (!visited[j] && dist[j] < min_dist) { min_dist = dist[j]; u = j; } } if (u == -1) { break; } visited[u] = 1; // 标记为已访问 // 更新与顶点u相邻的顶点的距离 for (Edge *edge = graph->vertices[u].head; edge != NULL; edge = edge->next) { int v = edge->dest; int w = edge->weight; if (!visited[v] && dist[u] + w < dist[v]) { dist[v] = dist[u] + w; prev[v] = u; } } } } // 打印最短路径 void print_path(Graph *graph, int start, int end, int *prev) { if (start == end) { printf("%d", start); } else if (prev[end] == -1) { printf("无路径"); } else { print_path(graph, start, prev[end], prev); printf("->%d", end); } } int main() { Graph graph; init_graph(&graph, 5); add_edge(&graph, 0, 1, 10); add_edge(&graph, 0, 3, 30); add_edge(&graph, 0, 4, 100); add_edge(&graph, 1, 2, 50); add_edge(&graph, 2, 4, 10); add_edge(&graph, 3, 2, 20); add_edge(&graph, 3, 4, 60); int dist[MAX_VERTEX_NUM]; int prev[MAX_VERTEX_NUM]; dijkstra(&graph, 0, dist, prev); for (int i = 1; i < graph.vertex_num; i++) { printf("0到%d的最短距离为%d,路径为", i, dist[i]); print_path(&graph, 0, i, prev); printf("\n"); } return 0; } ``` 该代码使用邻接表存储图,实现了Dijkstra算法,可以求解任意两个顶点之间的最短路径。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值