PTA: 旅游规划 [狄杰斯特拉+堆优化+链式前向星]

题目

输入样例:

4 5 0 3
0 1 1 20
1 3 2 30
0 3 4 10
0 2 2 20
2 3 1 20

输出样例:

3 40

思路

狄杰斯特拉几乎算是模版题。练了一下链式前向星。

代码

#include <cstdio>
#include <queue>
#include <cstring>

using namespace std;

const int maxn = 505;
struct Edge{
    int to, next, l, w;
}edge[maxn*maxn];
int tot = -1;
int head[maxn*maxn];
int n, m, s, d;

void add(int u, int v, int l, int w) {
    ++tot;
    edge[tot].to = v;
    edge[tot].l = l;
    edge[tot].w = w;
    edge[tot].next = head[u];
    head[u] = tot;
}

struct node{
    int to, l, w;
    node(int to, int l, int w) : to(to), l(l), w(w) {}
};
bool operator<(const node& a, const node& b) {
    if(a.l != b.l) {
        return a.l > b.l;
    }
    return a.w > b.w;
}
int dis[maxn];
int con[maxn];
priority_queue<node> que;
void dij() {
    memset(dis, 0x3f, sizeof(dis));
    memset(con, 0x3f, sizeof(con));
    que.push(node(s, 0, 0));
    dis[s] = con[s] = 0;
    while(que.size()) {
        auto tmp = que.top(); que.pop();
        for(int i = head[tmp.to]; i != -1; i = edge[i].next) {
            int tl = edge[i].l + tmp.l;
            int tw = edge[i].w + tmp.w;
            if(dis[edge[i].to] > tl) {
                dis[edge[i].to] = tl;
                con[edge[i].to] = tw;
                que.push(node(edge[i].to, tl, tw));
            }
            else if(dis[edge[i].to] == tl && con[edge[i].to]>tw) {
                con[edge[i].to] = tw;
                que.push(node(edge[i].to, tl, tw));
            }
        }
    }
}

int main(void)
{
    /* freopen("in.txt", "r", stdin); */
    scanf("%d%d%d%d", &n, &m, &s, &d);
    fill(head, head+n, -1);
    int u, v, w, l;
    while(m--) {
        scanf("%d%d%d%d", &u, &v, &l, &w);
        add(u, v, l, w);
        add(v, u, l, w);
    }
    dij();
    printf("%d %d\n", dis[d], con[d]);
    return 0;
}

狄杰斯特拉(Dijkstra)算法,也叫单源最短路径算法,是用于计算一个节点到其他所有节点的最短路径的算法。该算法常用于路由算法或作为其他图算法的一个子模块。 以下是狄杰斯特拉算法的基本思路: 1. 将所有节点分成两个集合:已知最短路径的节点集合和未知最短路径的节点集合。初始时,已知最短路径的节点集合只有起点,其他节点都在未知最短路径的节点集合中。 2. 对于所有的未知最短路径的节点,计算其到起点的距离,选择距离最小的节点加入已知最短路径的节点集合中。 3. 对于新加入已知最短路径的节点,更新其他未知最短路径的节点到起点的距离。 4. 重复步骤2和步骤3,直到所有节点都加入到已知最短路径的节点集合中。 以下是使用C++实现狄杰斯特拉算法的示例代码: ```c++ #include <iostream> #include <climits> using namespace std; #define V 6 // 图的顶点数 #define INF INT_MAX // 定义无穷大 // 查找未知最短路径中距离起点最近的节点 int minDistance(int dist[], bool sptSet[]) { int minDist = INT_MAX, minIndex; for(int i = 0; i < V; i++) { if(!sptSet[i] && dist[i] <= minDist) { minDist = dist[i]; minIndex = i; } } return minIndex; } // 执行狄杰斯特拉算法的函数 void dijkstra(int graph[V][V], int start) { int dist[V]; // 存储节点到起点的距离 bool sptSet[V]; // 存储节点是否已知最短路径 // 初始化dist数组和sptSet数组 for(int i = 0; i < V; i++) { dist[i] = INT_MAX; sptSet[i] = false; } dist[start] = 0; // 起点到起点的距离为0 for(int i = 0; i < V - 1; i++) { int u = minDistance(dist, sptSet); // 找到未知最短路径中距离起点最近的节点 sptSet[u] = true; // 将该节点加入已知最短路径的节点集合中 // 更新其他未知最短路径的节点到起点的距离 for(int v = 0; v < V; v++) { if(!sptSet[v] && graph[u][v] && dist[u] != INT_MAX && dist[u] + graph[u][v] < dist[v]) { dist[v] = dist[u] + graph[u][v]; } } } // 输出最短路径 cout << "节点\t\t到起点的距离" << endl; for(int i = 0; i < V; i++) { cout << i << "\t\t" << dist[i] << endl; } } int main() { int graph[V][V] = { {0, 2, 4, 0, 0, 0}, {2, 0, 1, 4, 2, 0}, {4, 1, 0, 0, 3, 0}, {0, 4, 0, 0, 3, 2}, {0, 2, 3, 3, 0, 2}, {0, 0, 0, 2, 2, 0} }; dijkstra(graph, 0); // 以0节点为起点执行狄杰斯特拉算法 return 0; } ``` 这个示例代码中的图是一个无向图,其邻接矩阵存储在graph数组中。运行程序后,将输出每个节点到起点的最短距离。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值