最短路问题

单源最短路

Dijkstra算法

最短路问题_第1张图片最短路问题_第2张图片

最短路问题_第3张图片

力扣 743.网络延迟时间

const int N = 7777;
int INF = 0x3f3f3f3f;
class Solution {
    struct edge {
        int v, w;
    };
    vector e[N];
    int d[N], vis[N];  //d数组存储最短路径长度
    priority_queue , vector>, greater>> heap;
public:
    int networkDelayTime(vector>& times, int n, int k) {
        for (vector ed : times) {
            e[ed[0]].push_back({ ed[1],ed[2] });
        }
        for (int i = 1; i <= n; i++) {
            d[i] = INF;
        }
        d[k] = 0;  //源点为0
        //first:源点到节点距离
        //second:节点
        heap.push({ 0,k });  
        while(!heap.empty()) {
            int u = heap.top().second;
            heap.pop();
            if (vis[u])
                continue;
            vis[u] = true;
            for (auto ed : e[u]) {
                int v = ed.v;
                int w = ed.w;
                if (!vis[v] && d[u] + w < d[v]) {
                    d[v] = d[u] + w;
                    heap.push({ d[u] + w, v });
                }
            }
        }
        int ans = 0;
        for (int i = 1; i <= n; i++) {
            if (d[i] == INF)
                return -1; 
            ans = max(ans, d[i]);
        }
        return ans;
    }
};

洛谷模板

#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include
#include
#include
using namespace std;
const int N = 5e5 + 10, INF = 0x3f3f3f3f;
struct edge {
	int v, w;
};
vector e[N];
int d[N], vis[N];  //d[i]表示源点到i点最短距离 ,vis表示是否从小根堆弹出过
priority_queue, vector>, greater>> heap;

int main() {
	int n, m, s;
	scanf("%d%d%d", &n, &m, &s);
    //邻接表建图
	for (int i = 0; i < m; i++) {
		int u, v, w;
		scanf("%d%d%d", &u, &v, &w);
		e[u].push_back({ v,w });
	}
	for (int i = 1; i <= n; i++) {
		d[i] = INF;
	}
	d[s] = 0;  //源点初始化为0
	heap.push({ 0,s });
	while (!heap.empty()) {
		auto u = heap.top().second;
		heap.pop();
		if (vis[u])
			continue;
		vis[u] = true;
		for (auto& ed : e[u]) {
		//first:源点到节点距离
		//second:节点
			int v = ed.v;
			int w = ed.w;
			if (!vis[v] && d[u] + w < d[v]) {
				d[v] = d[u] + w;
				heap.push({ d[u] + w, v });
			}
		}
	}
	for (int i = 1; i <= n; i++)
		printf("%d ", d[i]);
}

A*算法

最短路问题_第4张图片

const int N = 1001;

class Solution {
	int move[5] = { 1,0,-1,0,1 };
	int d[N][N];
	bool vis[N][N];
	struct edge {
		int x, y, w;
		bool operator>(const edge& other)const {
			return this->w > other.w;
		}
	};
	priority_queue, greater>heap;
public:
	//曼哈顿距离
	int f(int x, int y, int targetX, int targetY) {
		return abs(x - targetX) + abs(y - targetY);
	}

	int minDistance2(vector>& grid, int startX, int startY, int targetX, int targetY) {
		if (grid[startX][startY] == 0 || grid[targetX][targetY] == 0)
			return -1;
		int n = grid.size();
		int m = grid[0].size();
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				d[i][j] = INT_MAX;
			}
		}
		d[startX][startY] = 1;
		heap.push({ startX,startY,1+f( startX, startY, targetX, targetY)});
		while (!heap.empty()) {
			auto cur = heap.top();
			int x = cur.x;
			int y = cur.y;
			if (vis[x][y])
				continue;
			vis[x][y] = true;
			for (int i = 0; i < 4; i++) {
				int nx = move[i] + x;
				int ny = move[i + 1] + y;
				if (nx >= 0 && ny >= 0 && nx < n && ny < m && !vis[nx][ny]) {
					d[nx][ny] = d[x][y] + 1;
					heap.push({ nx,ny,1 + d[x][y] + f(nx,ny,targetX,targetY) });
				}
			}
		}
		return -1;
	}
};

Bellman-Ford与SPFA优化

最短路问题_第5张图片

最短路问题_第6张图片

SPFA流程

最短路问题_第7张图片

最短路问题_第8张图片

洛谷模板

#include
#include
#include
#include
#include

using namespace std;
const int N = 4e6 + 10;

struct edge {
    int v, w, ne;
}e[N];
int h[N]; int idx = 1;
int d[N], q[N];  //d[i]源点到节点距离的表 q[i]哪些节点被松弛了放入队列
bool st[N];  //节点是否在队列中
int cnt[N];  //节点被松弛次数
int l = 0, r = 0;

void add(int u, int v, int w) {
    e[idx] = { v,w,h[u] };
    h[u] = idx++;
}

bool  SPFA(int n) {
    d[1] = 0;
    cnt[1]++;
    q[r++] = 1;
    st[1] = true;
    while (l < r) {
        int u = q[l++];
        st[u] = false;
        //考察从u出发的所有边
        for (int i = h[u]; i > 0; i = e[i].ne) {
            int v = e[i].v;
            int w = e[i].w;
            if (d[u] + w < d[v]) {
                d[v] = d[u] + w;
                if (!st[v]) {
                    if (cnt[v]++ >= n)  //松弛次数为n 说明有负环
                        return true;
                    q[r++] = v;
                    st[v] = true;
                }
            }
        }
    }
    return false;
}

int main() {
    int t;
    scanf("%d", &t);
    while (t--) {
        l = r = 0;
        memset(e, 0, sizeof(e));
        memset(h, 0, sizeof(h));
        memset(cnt, 0, sizeof(cnt));
        memset(d, 0x7f, sizeof(d));
        memset(st, 0, sizeof(st));
        idx = 1;
        int n, m;
        scanf("%d%d", &n, &m);
        for (int i = 0; i < m; i++) {
            int u, v, w;
            scanf("%d%d%d", &u, &v, &w);
            add(u, v, w);
            if (w >= 0) {
                add(v, u, w);
            }
        }
        printf("%s", SPFA(n) ? "YES\n" : "NO\n");
    }
    return 0;
}

多源最短路

Floyd算法

最短路问题_第9张图片

#include
#include
#include
using namespace std;
const int N = 111, M = 11111;
int d[N][N], path[M];
int n, m;

void floyed() {
	for (int k = 1; k <= n; k++) {
		for (int i = 1; i <= n; i++) {
			for (int j = 1; j <= n; j++) {
				d[i][j] = min(d[i][k] + d[k][j], d[i][j]);
			}
		}
	}
}

int main() {
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= m; i++) {
		scanf("%d", &path[i]);
	}
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			d[i][j] = INT_MAX;
		}
	}
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			scanf("%d", &d[i][j]);
		}
	}
	floyed();
	int ans = 0;
	for (int i = 2; i <=m; i++) {
		ans += d[path[i - 1]][path[i]];
	}
	printf("%d", ans);
}

你可能感兴趣的:(算法)