3 条题解

  • 1
    @ 2024-6-30 10:52:06

    回顾一下最短路径的算法:

    • 所有顶点间的最短路径算法 --- Floyd
    • 单源最短路径算法 --- Dijkstra
    • 判断负权回路最短路径算法 --- Bellman-Ford
    • 带负权边最短路径算法 --- SPFA

    最短路径:在带权有向图中 AA 点(源点)到 BB 点(终点)的多条路径中,寻找一条各边权值最小的路径,即最短路径

    可以用 Dijkstra 算法解决单源最短路径问题。

    基本思想

    将图中所有顶点分成两组:已知确定最短路 SS、尚未确定最短路 VSV-S不断从第 22 组中选择路径长度最短的点放入第 11 组并扩展。

    若顶点序列 V0,V1,......,Vn{V_0,V_1,......,V_n} 是从 V0V_0VnV_n 的最短路,则序列 V0,V1,......,Vn1{V_0,V_1,......,V_{n-1}} 必为从 V0V_0Vn1V_{n-1} 的最短路。

    其本质为:贪心算法,且只能用于正权图。

    可以用优先队列 priority_queuepriority\_queue 和邻接表来优化。

    注意:本题要开 long longlong\ long

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    typedef long long ll;
    const int N = 5e5 + 10;
    int h[N], vtx[2 * N], nxt[2 * N], wt[2 * N], idx;
    int dis[N], pre[N], vis[N];
    int n, m, s, tu, tv, tw;
    
    struct node {
    	int u, v, w;
    	friend bool operator < (node a, node b) {
    		if (a.w >= b.w) {
    			return 1;
    		} else {
    			return 0;
    		}
    	}
    };
    priority_queue<node> q;
    
    void addEdge(int a, int b, int c) {
    	vtx[idx] = b;
    	nxt[idx] = h[a];
    	wt[idx] = c;
    	h[a] = idx++;
    }
    
    void dijkstra(int s) {
    	dis[s] = 0;
    	node tmp;
    	tmp.u = s;
    	tmp.v = s;
    	tmp.w = 0;
    	q.push(tmp);
    	while (!q.empty()) {
    		tmp = q.top();
    		q.pop();
    		int nid = tmp.v;
    		if (vis[nid] == 1) {
    			continue;
    		}
    		vis[nid] = 1;
    		int p = h[nid];
    		while (p != -1) {
    			if (vis[vtx[p]] == 0) {
    				if (dis[nid] + wt[p] < dis[vtx[p]]) {
    					dis[vtx[p]] = dis[nid] + wt[p];
    					pre[vtx[p]] = nid;
    					tmp.u = nid;
    					tmp.v = vtx[p];
    					tmp.w = dis[vtx[p]];
    					q.push(tmp);
    				}
    			}
    			p = nxt[p];
    		}
    	}
    }
    signed main() {
    	memset(h, -1, sizeof(h));
    	cin >> n >> m >> s;
    	for (int i = 1; i <= n; i++) {
    		dis[i] = 3e18;
    	}
    	while (m--) {
    		cin >> tu >> tv >> tw;
    		if (tu != tv) {
    			addEdge(tu, tv, tw);
    		}
    	}
    	dijkstra(s);
    	for (int i = 1; i <= n; i++) {
    		if (s == i) {
    			cout << 0 << " "; 
    		} else {
    			cout << dis[i] << " ";
    		}
    	}
    	return 0;
    }
    

    信息

    ID
    223
    时间
    1000ms
    内存
    256MiB
    难度
    7
    标签
    (无)
    递交数
    313
    已通过
    67
    上传者