主要处理问题:最小生成树问题。
算法思想:V表示所有节点集合,首先s进入集合U,然后找出集合U与剩余节点V-U中最小权值的边[u,v],将v加入集合U,直到U==V截至
时间复杂度:相对与Kruskal需要多次排序,>>O(E)
主要处理问题:最小生成树问题。
算法思想:对所有边按照权值进行排序,然后使用并查集,将所有节点加入到集合中。
时间复杂度:O(E)
主要处理问题:权值为正,单源点最短路径问题
算法思想:N-1次松弛,每次找出没有被访问过d值最小的节点x,然后对所有与x相连的节点进行松弛
时间复杂度:O(N*N),比较稳定
主要处理问题:权值为负,无负环,单源点最短路径问题
算法思想:N-1次松弛,每次历遍完所有边进行松弛
时间复杂度:O(N*E)
主要处理问题:权值为负,无负环,单源点最短路径问题。或者稀疏图,邻接表实现
算法思想:bfs+松弛,队实现,首先s入队,输出队首元素u,然后历遍与u相连的所有边[u,v],然后进行松弛,如果松弛成功,并且v没有在队中,则将v入队。
时间复杂度:O(E) --- O(N*E),不稳定
拓展:如果某一个节点入队超过N-1次,则存在负环
//Dijkstra int dijkstra(int s, int e) { for(i = 0; i < N; ++ i) d[i] = INF; d[s] = 0; memset(vis, 0, sizeof(vis)); for(i = 0; i < N - 1; ++ i) { int x = 0; for(j = 0; j <= N; ++ j) if(!vis[j] && d[j] < d[x]) x = j; vis[x] = 1; for(j = 0; j <= N; ++ j) if(map[x][j] && d[j] > d[x] + map[x][j]) d[j] = d[x] + map[x][j]; } return d[e]; } //SPFA struct Node { int v, w; }; vector<Node> G[nMax]; int vis[nMax]; int spfa(int s, int e) { memset(vis, 0, sizeof(vis)); for(i = 0; i < N; ++ i) dis[i] = INF; dis[s] = 0; queue<int> que; que.push(s); while(!que.empty()) { int u = que.front(); que.pop(); vis[u] = 0; for(i = 0; i < G[u].size(); ++ i) { Node tmp = G[u][i]; if(dis[tmp.y] > dis[u] + tmp.w) { dis[tmp.y] = dis[u] + tmp.w; if(!vis[tmp.y]) { vis[tmp.y] = 1; que.push(tmp.y); } } } } return dis[e]; } //Floyd for(k = 0; k < N; ++ k) for(i = 0; i < N; ++ i) for(j = 0; j < N; ++ j) if(d[i][j] > d[i][k] + d[k][j]) d[i][j] = d[i][k] + d[k][j];