• 备战NOIP——模板复习10


    这里只有模板,并不作讲解,仅为路过的各位做一个参考以及用做自己复习的资料,转载注明出处。

    最短路算法

    Dijkstra + 堆优化

    /*Copyright: Copyright (c) 2018
    *Created on 2018-11-1  
    *Author: 十甫
    *Version 1.0 
    *Title: Dijkstra + heap
    *Time: 10 mins
    */
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<queue>
    using namespace std;
    const int maxn = 10005;
    const int maxm = 10005;
    
    int head[maxn];
    struct edge {
    	int to, val, next;
    } data[maxm * 2];
    inline void add_edge(int from, int to, int val, int i) {
    	data[i] = (edge) {to, val, head[from]};
    	head[from] = i;
    }
    int n, m;
    int dis[maxn];
    bool vis[maxn];
    struct node {
    	int dist, ord;
    	bool operator < (const node cmp) const {
    		return dist > cmp.dist;
    	}
    };
    void Dij(int p) {
    	memset(dis, 0x3f, sizeof(dis));
    	memset(vis, false, sizeof(vis));
    	dis[p] = 0;
    	priority_queue <node> q;
    	q.push((node) {dis[p], p});
    	for(int i = 1;i < n;i++) {
    		while(vis[q.top().ord]) q.pop();
    		node tmp = q.top();
    		int u = tmp.ord;
    		q.pop();
    		vis[u] = true;
    		for(int i = head[u];i;i = data[i].next) {
    			int v = data[i].to, k = data[i].val;
    			if(dis[v] > dis[u] + k) {
    				dis[v] = dis[u] + k;
    				q.push((node) {dis[v], v});
    			}
    		}
    	}
    }
    
    int main() {
    	scanf("%d%d", &n, &m);
    	for(int i = 1;i <= m;i++) {
    		int a, b, c;
    		scanf("%d%d%d", &a, &b, &c);
    		add_edge(a, b, c, i), add_edge(b, a, c, i + m);
    	}
    	int p;
    	scanf("%d", &p);
    	Dij(p);
    	for(int i = 1;i <= n;i++) {
    		printf("%d ", dis[i]);
    	}
    	printf("
    ");
    	return 0;
    }

    Floyd

    /*Copyright: Copyright (c) 2018
    *Created on 2018-11-1  
    *Author: 十甫
    *Version 1.0 
    *Title: Floyd
    *Time: 4 mins
    */
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    using namespace std;
    const int size = 605;
    inline int Min(int a, int b) {
    	return a < b ? a : b;
    }
    
    int n, m, dis[size][size];
    void Floyd() {
    	for(int k = 1;k <= n;k++) {
    		for(int i = 1;i <= n;i++) {
    			for(int j = 1;j <= n;j++) {
    				dis[i][j] = Min(dis[i][j], dis[i][k] + dis[k][j]);
    			}
    		}
    	}
    }
    
    int main() {
    	scanf("%d%d", &n, &m);
    	memset(dis, 0x3f, sizeof(dis));
    	for(int i = 1;i <= n;i++) {
    		dis[i][i] = 0;
    	}
    	for(int i = 1;i <= m;i++) {
    		int a, b, c;
    		scanf("%d%d%d", &a, &b, &c);
    		dis[a][b] = dis[b][a] = Min(dis[a][b], c);
    	}
    	Floyd();
    	int q;
    	scanf("%d", &q);
    	while(q--) {
    		int a, b;
    		scanf("%d%d", &a, &b);
    		printf("%d
    ", dis[a][b]);
    	}
    	return 0;
    }

    SPFA

    /*Copyright: Copyright (c) 2018
    *Created on 2018-11-1  
    *Author: 十甫
    *Version 1.0 
    *Title: SPFA
    *Time: 7 mins
    */
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<queue>
    using namespace std;
    const int maxn = 10005;
    const int maxm = 10005;
    
    int head[maxn];
    struct edge {
    	int to, val, next;
    } data[maxm * 2];
    inline void add_edge(int from, int to, int val, int i) {
    	data[i] = (edge) {to, val, head[from]};
    	head[from] = i;
    }
    int n, m, dis[maxn];
    bool vis[maxn];
    void SPFA(int p) {
    	memset(dis, 0x3f, sizeof(dis));
    	memset(vis, false, sizeof(vis));
    	dis[p] = 0, vis[p] = true;
    	queue <int> q;
    	q.push(p);
    	while(!q.empty()) {
    		int u = q.front();
    		q.pop();
    		for(int i = head[u];i;i = data[i].next) {
    			int v = data[i].to, k = data[i].val;
    			if(dis[v] > dis[u] + k) {
    				dis[v] = dis[u] + k;
    				if(!vis[v]) q.push(v);
    			}
    		}
    		vis[u] = false;
    	}
    }
    
    int main() {
    	scanf("%d%d", &n, &m);
    	for(int i = 1;i <= m;i++) {
    		int a, b, c;
    		scanf("%d%d%d", &a, &b, &c);
    		add_edge(a, b, c, i), add_edge(b, a, c, i + m);
    	}
    	int p;
    	scanf("%d", &p);
    	SPFA(p);
    	for(int i = 1;i <= n;i++) {
    		printf("%d ", dis[i]);
    	}
    	printf("
    ");
    	return 0;
    }

    如果图包含负环的话,可以利用SPFA判断负环, 具体做法参考@forever_dreams 的Blog


    用 cnt[ i ] 表示从起点(假设就是 1)到 i 的最短距离包含点的个数,初始化 cnt[ 1 ] = 1,那么当我们能够用点 u 松弛点 v 时,松弛时同时更新 cnt[ v ] = cnt[ u ] + 1,若发现此时 cnt[ v ] > n,那么就存在负环
    原文链接:  SPFA判负环


    NOIP 2018 RP++
  • 相关阅读:
    iReaper
    展望未来,总结过去10年的程序员生涯,给程序员小弟弟小妹妹们的一些总结性忠告(turn)
    用C#写ExtJS代码的开源工具extsharp
    如何你是公司的HR,去招聘asp.net程序员,你会对前来面试的人问什么问题。
    ExtJS 3.0 Designer Preview (官方的IDE可视化工具)
    Asp.net ajax、Anthem.net、Ajax pro三大ajax框架那一种使用比较方便?易于配置?
    C#和ASP.net程序员招聘技能要求
    序列化上面创建的Person对象,使其成为一个JSON字符串
    10大加速Ajax开发的框架
    android 解决wifi断线不稳定的问题终极办法
  • 原文地址:https://www.cnblogs.com/Black-S/p/9930714.html
Copyright © 2020-2023  润新知