• 最短路算法


    Floyd

    纯暴力,三个 for 循环

    复杂度: (O(V^3))

    for(int k = 1;k <= n;k++){
    	for(int i = 1;i <= n;i++){
    		for(int j = 1;j <= n;j++){
    			if(dis[i][k] + dis[k][j] < dis[i][j]){
    				//...
    			}
    		}
    	}
    }
    

    Bellman-Ford

    用边去进行松弛操作,可以判环

    复杂度: (O(VE))

    #include<bits/stdc++.h>
    using namespace std;
    
    const int maxm = 2e5 + 10;
    const int maxn = 1e5 + 10;
    
    struct E {
    	int from, to, w;
    }Edges[maxm];
    
    int dis[maxn];
    int n, m, s;
    
    bool bellman_ford(int s) {
    
    	for (int i = 1; i < n; i++) {//松弛n-1次
    		for (int j = 0; j < m; j++) {
    			int f = Edges[j].from, t = Edges[j].to, w = Edges[j].w;
    			if (dis[t] > dis[f] + w) {
    				dis[t] = dis[f] + w;
    			}
    		}
    	}
    
    	for (int j = 0; j < m; j++) {
    		int f = Edges[j].from, t = Edges[j].to, w = Edges[j].w;
    		if (dis[t] > dis[f] + w) {
    			return false;//负环
    		}
    	}
    	return true;
    }
    int main() {
    	scanf("%d %d %d", &n, &m, &s);
    	memset(dis, 0x3f, sizeof dis);
    	dis[s] = 0;//注意dis的初始化
    	for (int i = 0; i < m; i++) {
    		scanf("%d%d%d", &Edges[i].from, &Edges[i].to, &Edges[i].w);
    		if (Edges[i].from == s) {
    			dis[Edges[i].to] = Edges[i].w;//初始化
    		}
    	}
    	bellman_ford(s);
    	for (int i = 1; i <= n; i++) {
    		printf("%d%s", dis[i], i == n ? "
    " : " ");
            //printf("%d%c",dis[i]," 
    "[i==n]);
    	}
    }
    

    Dijkstra

    复杂度(O(VlogV+E))

    struct Node {
    	long long d;
    	int u;
    	bool operator < (const Node& rhs)const { 
            //rhs,right-hand-side
    		return d > rhs.d;
    	}
    };
    
    void dijkstra(int s) {
    	priority_queue<Node>Q;
    	for (int i = 1;i <= n;i++) {
    		d[i] = INF;
    	}
    	d[s] = 0;
    
    	memset(vis, 0, sizeof(vis));
    	Q.push(Node{ 0,s });
    	
    	while (!Q.empty()) {
    		Node x = Q.top();Q.pop();
    
    		int u = x.u;
    
    		if (vis[u]) {
    			continue;
    		}
    
    		vis[u] = 1;
    
    		for (int i = 0;i < G[u].size();i++) {
    			Edge e = edges[G[u][i]];
    			if (d[e.to] > d[u] + e.dist) {
    				d[e.to] = d[u] + e.dist;
    				p[e.to] = G[u][i];
    				Q.push(Node{ d[e.to],e.to });
    			}
    		}
    	}
    }
    

    SPFA

    (O(kE))(k) 为每个节点入队次数

    最坏 (O(EV))

    #include<bits/stdc++.h>
    using namespace std;
    
    const int maxn = 1e6 + 10;
    struct Edge {
    	int to, w, next;
    }E[maxn];
    
    int head[maxn], tot;
    
    void AddEdge(int from, int to, int w) {
    	E[tot] = Edge{ to,w,head[from] };
    	head[from] = tot++;
    }
    
    int n, m, s;
    const int inf = 0x3f3f3f3f;// inf > (1e9)
    int dis[maxn], vis[maxn];
    
    void spfa() {
    	queue<int> q;
    	memset(dis, 0x3f, sizeof(int) * (n + 10));
    	memset(vis, 0, sizeof(int) * (n + 10));
    
    	q.push(s); dis[s] = 0; vis[s] = 1; //第一个顶点入队,进行标记
    	while (!q.empty()) {
    		int u = q.front();
    		q.pop(); vis[u] = 0;
    		for (int i = head[u]; ~i; i = E[i].next) {
    			int v = E[i].to;
    			if (dis[v] > dis[u] + E[i].w) {
    				dis[v] = dis[u] + E[i].w;
    				if (vis[v] == 0) {
                        //此处判环
                        //if(++cnt[v] >= n) 有负环
    					vis[v] = 1;
    					q.push(v);
    				}
    			}
    		}
    	}
    }
    
    int main() {
    
    	scanf("%d%d%d", &n, &m, &s);
    	memset(head, 0xff, sizeof(int) * (n + 10));
    	tot = 0;
    	for (int i = 0; i < m; i++) {
    		int a, b, w;
    		scanf("%d%d%d", &a, &b, &w);
    		AddEdge(a, b, w);
    	}
    	spfa();
    	for (int i = 1; i <= n; i++) {
    		printf("%d%c", dis[i] == 0x3f3f3f3f ? (1 << 31) - 1 : dis[i], " 
    "[i == n]);
    	}
    }
    
  • 相关阅读:
    socket详解(二)----实例和多线程,线程池使用
    OpenJDK和JDK区别
    单词(11)
    程序员到项目经理:从内而外的提升(比较全面的介绍)
    如何成为一名自然语言处理工程师
    权限设计文章汇总
    ECharts+百度地图,默认选中 卫星地图
    Echarts3.0 引入百度地图(转载)
    echarts地图 鼠标滚动控制缩放大小比例(转载)
    echarts散点图 不显示问题 或宽度为0问题
  • 原文地址:https://www.cnblogs.com/sduwh/p/13651423.html
Copyright © 2020-2023  润新知