1.2.1 分算法之Dijkstra

算法本质是贪心,一些不像图论的可贪心的让求关于单源的解的题也能用哦。不能解决负权边。
Eg1.佳佳的魔法药水一道看起来和最短路没啥关系的题,但是可以贪心啊,每次找一个值最小但却没有确定最小值的药水,将其标记为最小值,然后枚举能与此药水合成药水的药水,用找到的药水与配对的药水更新合成药水的最小值,和Dij相似。
#include<bits/stdc++.h>
using namespace std;const int maxn = 1010;
const int inf = 0x3f3f3f3f;int n, p[maxn], ans[maxn], now, mp[maxn][maxn];
bool vis[maxn];void Dijkstra(){for(int i = 1; i < n; i++){int low = inf;for(int j = 1; j <= n; j++)if(!vis[j] && p[j] < low){low = p[j];now = j;}vis[now] = 1;for(int j = 1; j <= n; j++)if(vis[j] && mp[now][j]){//Dij要找已松弛的!!!! if(p[mp[now][j]] > p[now] + p[j]){ans[mp[now][j]] = ans[now] * ans[j];p[mp[now][j]] = p[now] + p[j];}else if(p[mp[now][j]] == p[now] + p[j])ans[mp[now][j]] += ans[now] * ans[j];}}
}int main(){scanf("%d", &n);for(int i = 1; i <= n; i++){scanf("%d", &p[i]);//表示初始都是靠买哒 ans[i] = 1;}int x, y, z;while(scanf("%d%d%d", &x, &y, &z) != EOF)mp[x+1][y+1] = mp[y+1][x+1] = z + 1;Dijkstra();printf("%d %d\n", p[1], ans[1]);return 0;
}
Eg2.板子
#include<bits/stdc++.h>
using namespace std;const int maxn = 1010;
const int inf = 0x3f3f3f3f;struct data{int v, w, nxt;
} edge[maxn*maxn*2];struct node{int point, w;bool operator < (const node& a) const {return w < a.w;}
};int dis[maxn], vis[maxn], st[maxn];
int n, m, tot;inline void in(int x, int y, int z){edge[++tot].v = y;edge[tot].w = z;edge[tot].nxt = st[x];st[x] = tot;
}inline void Dijkstra(){priority_queue<node> q;for(int i = 0; i <= n; i++) dis[i] = inf;q.push((node){1, 0});dis[1] = 0;while(!q.empty()){node now = q.top(); q.pop();if(vis[now.point])  continue;vis[now.point] = 1;for(int i = st[now.point]; i; i = edge[i].nxt){int to = edge[i].v;if(dis[to] > dis[now.point] + edge[i].w){dis[to] = dis[now.point] + edge[i].w;q.push((node){to, dis[to]});}}}printf("%d\n", dis[n]);
}int main(){scanf("%d%d", &n, &m);for(int i = 1, x, y, z; i <= m; i++){scanf("%d%d%d", &x, &y, &z);in(x, y, z);in(y, x, z); }Dijkstra();return 0;
}

1.2.2 SPFA

自用最短路板子!!!可求瓶颈路!不太稳啊。。希望不被卡。。
Eg1.营救瓶颈路!!!就是让路上的最大值尽量小!!!把加号改成max即可!
#include<bits/stdc++.h>
using namespace std;
const int maxn = 100010;
int n, m, s, t, tot;
int d[maxn], st[maxn];
bool vis[maxn];
queue<int> q;
struct node{int v, w, nxt;
} edge[2*maxn];inline void in(int x, int y, int z){edge[++tot].v = y;edge[tot].w = z;edge[tot].nxt = st[x];st[x] = tot;
}inline void spfa(){memset(d, 0x3f3f3f3f, sizeof(d));q.push(s);vis[s] = 1;d[s] = 0;while(!q.empty()){int now = q.front(); q.pop();vis[now] = 0;for(int i = st[now]; i; i = edge[i].nxt){int to = edge[i].v;if(max(d[now], edge[i].w) < d[to]){d[to] = max(d[now], edge[i].w);vis[to] = 1;q.push(to);}}}
}int main(){scanf("%d%d%d%d", &n, &m, &s, &t);for(int i = 1, x, y, z; i <= m; i++){scanf("%d%d%d", &x, &y, &z);in(x, y, z);in(y, x, z);}spfa();printf("%d\n", d[t]);return 0;
} 
Eg2.玛丽卡求出最短路然后枚举最短路上的边一一删除,关键在于记录路径的方式,path[to] = i即可,然后用链表来遍历!
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1010;
const int inf = 0x3f3f3f3f;
int tot, n, m, cnt;
struct node{int u, v, w, next;
} edge[maxn*maxn];
int st[maxn], d[maxn], fe[maxn*maxn];
bool v[maxn];void in(int a, int b, int c){edge[++tot].u = a;edge[tot].v = b;edge[tot].w = c;edge[tot].next = st[a];st[a] = tot;
}void init(){memset(v, 0, sizeof(v));for(int i = 0; i <= n; i++)d[i] = inf;
}void spfa(int begin, int end, int judge){queue<int> q;init();d[begin] = 0;v[begin] = 1;q.push(begin);while(!q.empty()){int from = q.front(); q.pop();v[from] = 0;for(int i = st[from]; i > 0; i = edge[i].next){int to = edge[i].v;if(d[to] > d[from] + edge[i].w){d[to] = d[from] + edge[i].w;if(judge)fe[to] = i;if(!v[to]){v[to] = 1;q.push(to);}}}}
}int main(){cin >> n >> m;for(int j = 1, a, b, c; j <= m; j++){cin >> a >> b >> c;in(a, b, c);in(b, a, c);}memset(fe, -1, sizeof(fe));spfa(n, 1, 1);int ans = d[1];//cout << ans << endl;for(int i = fe[1]; i > 0; i = fe[edge[i].u]){//cout << edge[i].v << " ";int t = edge[i].w;//cout << t << endl;edge[i].w = inf;spfa(n, 1, 0);//cout << d[1] << endl;edge[i].w = t;ans = max(ans, d[1]);}cout << ans << endl;return 0;
}
Eg3.小K的农场差分约束系统,a-b >= c 则建一条b到a权值为c的边,a = b则建权值为0的双向边,然后跑SPFA的**DFS版**判负环,这样效率为O(n)。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
typedef long long Lovelive;
using namespace std;
inline void scan(int &x) {int f = 1; x = 0;char c = getchar();while(c > '9' || c < '0') {if(c == '-') f= -1; c = getchar();}while(c >= '0' && c <= '9') x = x*10 + c - '0', c = getchar();f*x;
}
const int maxn=2e4+10;
int n, m;
struct Edge {int v, next, val;
}e[maxn];
int last[maxn], tot;
void add(int u, int v, int w) {e[++tot].next=last[u]; e[tot].v=v; e[tot].val=w; last[u]=tot;
}
int dis[maxn];
bool vis[maxn];
bool SPFA(int u) {vis[u]=1;for(int i=last[u]; i; i=e[i].next) {if(dis[e[i].v] > dis[u]+e[i].val) {dis[e[i].v] = dis[u]+e[i].val;if(vis[e[i].v]) return false;else if(!SPFA(e[i].v)) return false;}}vis[u]=0;return true;
}
int main() {scan(n); scan(m);while(m--) {int k; scan(k);if(k == 3) { int a, b; scan(a), scan(b); add(b, a, 0); add(a, b, 0);}else {int a, b, c;scan(a); scan(b); scan(c);if(k==1) add(a, b, -c);else add(b, a, c);}}for(int i=0; i<=n; i++) add(0, i, 0), dis[i]=maxn;dis[0]=0;if(SPFA(0)) cout << "Yes";else cout << "No";return 0;
}
    Eg4.最小圈分数规划,同样用SPFA判负环,二分答案。
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
inline int read() {int res = 0; bool bo = 0; char c;while (((c = getchar()) < '0' || c > '9') && c != '-');if (c == '-') bo = 1; else res = c - 48;while ((c = getchar()) >= '0' && c <= '9')res = (res << 3) + (res << 1) + (c - 48);return bo ? ~res + 1 : res;
}
const int N = 3005, M = 1e4 + 5; const double eps = 1e-9;
int n, m, ecnt, nxt[M], adj[N], go[M], w[M]; double val[M], dis[N];
bool Flag, vis[N];
void add_edge(int u, int v, int x) {nxt[++ecnt] = adj[u]; adj[u] = ecnt; go[ecnt] = v; w[ecnt] = x;
}
void dfs(int u) {vis[u] = 1;for (int e = adj[u], v; e; e = nxt[e])if (dis[u] + val[e] < dis[v = go[e]]) {if (vis[v]) return (void) (Flag = 1);else {dis[v] = dis[u] + val[e];dfs(v);}}vis[u] = 0;
}
bool check(double x) {int i; memset(vis, 0, sizeof(vis));for (i = 1; i <= ecnt; i++) val[i] = 1.0 * w[i] - x;memset(dis, 0, sizeof(dis));for (i = 1; i <= n; i++) {Flag = 0;if (dfs(i), Flag) return 1;}return 0;
}
double solve() {double l = -1e5, r = 1e5;while (fabs(r - l) > eps) {double mid = (l + r) / 2;if (check(mid)) r = mid;else l = mid;}return l;
}
int main() {int i, x, y, z; n = read(); m = read();for (i = 1; i <= m; i++) x = read(), y = read(),z = read(), add_edge(x, y, z);printf("%.8lf\n", solve());return 0;
}

1.2.3 Floyd
预处理多元会用到
Eg1.Vijos 观光旅游
判最小正环

    //设环的起点(终点)为i,那么环可以表示为i->k->j->x1,x2...(不经过k)->i//环的长度可以表示为i->j经过k的dist+i->不经过k的dist//i->j经过k的dist普通floyd就能求到,不经过k的dist需要构造//在求这个环时,保持k是最大值,那么所有x1,x2...都比k要小//循环遍历至k-1时存储的就是j->x1,x2...->i的最小值 for(int k=1;k<=n;k++){//k是用来更新的中间点,保持k比i,j都要大, for(int i=1;i<k;i++)//floyd每次更新从i开始到j结束,中间经过k的距离for(int j=i+1;j<k;j++){ans=min(ans,dist[i][j]+edge[i][k]+edge[k][j]);}for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)dist[i][j]=min(dist[i][j],dist[i][k]+dist[k][j]);} if(ans<INF) printf("%d\n",ans);

1.2 最短路算法的多用相关推荐

  1. spfa算法_10行实现最短路算法——Dijkstra

    今天是算法数据结构专题的第34篇文章,我们来继续聊聊最短路算法. 在上一篇文章当中我们讲解了bellman-ford算法和spfa算法,其中spfa算法是我个人比较常用的算法,比赛当中几乎没有用过其他 ...

  2. 最短路算法总结(入门版)

    最近花了大约一个月左右的时间集中刷了一些图论的题目.虽然收获了许多但是还是付出了很多作业没有做的代价0.0.在这里先把自己所做的关于最短路的基础算法来做一个总结,至少把学到的东西记录下来. 先说明一下 ...

  3. dijkstra算法matlab程序_编程习题课 | 用最短路算法为你的小地图导航

    简介:路网拓扑的正确导入方式,运筹学算法的完整实战案例,最详细的代码讲解与分享. 引言:在研究路径选择和流量分配等交通问题时,常常会用到最短路算法.用最短路算法解决交通问题存在两个难点:一.算法的选择 ...

  4. 坐在马桶上看算法:Dijkstra最短路算法

                                                             [坐在马桶上看算法]算法7:Dijkstra最短路算法 上周我们介绍了神奇的只有五行的 ...

  5. 坐在马桶上看算法:只有五行的Floyd最短路算法

    坐在马桶上看算法:只有五行的Floyd最短路算法 此算法由Robert W. Floyd(罗伯特·弗洛伊德)于1962年发表在"Communications of the ACM" ...

  6. 疯子的算法总结(八) 最短路算法+模板

    Dijkstra:适用于权值为非负的图的单源最短路径,用斐波那契堆的复杂度O(E+VlgV) BellmanFord:适用于权值有负值的图的单源最短路径,并且能够检测负圈,复杂度O(VE) SPFA: ...

  7. Dijkstra 最短路算法(只能计算出一条最短路径,所有路径用dfs)

    上周我们介绍了神奇的只有五行的 Floyd 最短路算法,它可以方便的求得任意两点的最短路径,这称为"多源最短路".本周来来介绍指定一个点(源点)到其余各个顶点的最短路径,也叫做&q ...

  8. lee最短路算法_Lee算法的解释:迷宫运行并找到最短路径

    lee最短路算法 Lee算法是什么? (What is the Lee Algorithm?) The Lee algorithm is one possible solution for maze ...

  9. zuc算法代码详解_最短路算法-dijkstra代码与案例详解

    引言 在研究路径选择和流量分配等交通问题时,常常会用到最短路算法.用最短路算法解决交通问题存在两个难点: 一.算法的选择和程序的编写.最短路算法有很多种改进算法和启发式算法,这些算法的效率不同,适用的 ...

最新文章

  1. sqlite-1.0.0源码执行的基本流程概述
  2. bootstrap 树形表格渲染慢_bootstrap-table-treegrid数据量较大时渲染太久了
  3. ASM元数据备份与恢复:md_backup和md_restore
  4. Windows 7 下 Node.js 连接 Oracle
  5. python编写代码时零_python – KeyError:运行打包代码时为0L
  6. [css] 头部设置meta也可以做到自适应为啥还要用rem?
  7. Could not open ServletContext resource [/WEB-INF/applicationContext.xml]”解决方案
  8. 多线程编程学习总结(转载)
  9. IDEA安装“Alibaba Java Coding Guidelines”插件
  10. CURL -w 参数详解
  11. ADC采样频率的计算
  12. diameter协议栈_Diameter协议摘要
  13. 2007软件英雄会暨CSDN社区英雄榜颁奖典礼邀请人员名单
  14. 计算机管理映像路径,windows任务管理器显示映像路径和命令行设置参考
  15. CCF 1158. 骰子游戏
  16. 环境变量使用与何时使用环境变量
  17. 如何在Joomla中创建一个漂亮的单页网站
  18. simulink 报错Derivative of state ‘1‘ in block ..... at time 0.0 is not finite.
  19. 那天,比尔・盖茨差点“砍掉”了这个 160 亿美元的项目:不运行 Windows,是种侮辱...
  20. cmos图像传感器简介

热门文章

  1. JavaScript实现计时器
  2. mysql整数转为2位小数_SQL整数转换成小数
  3. 随机数rand和srand的用法
  4. pointnet train 第十句correct = tf.equal(tf.argmax(pred, 1), tf.to_int64(labels_pl))
  5. AliCDN,盛开在云端的花朵
  6. 搜遍全网,终于找到一个适合新手入门的物联网教程
  7. nginx重启报找不到nginx.pid的解决方法
  8. python中的path的使用
  9. 《千手智能打铃》使用说明
  10. Windows环境下编译Airsim