1.2 最短路算法的多用
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 最短路算法的多用相关推荐
- spfa算法_10行实现最短路算法——Dijkstra
今天是算法数据结构专题的第34篇文章,我们来继续聊聊最短路算法. 在上一篇文章当中我们讲解了bellman-ford算法和spfa算法,其中spfa算法是我个人比较常用的算法,比赛当中几乎没有用过其他 ...
- 最短路算法总结(入门版)
最近花了大约一个月左右的时间集中刷了一些图论的题目.虽然收获了许多但是还是付出了很多作业没有做的代价0.0.在这里先把自己所做的关于最短路的基础算法来做一个总结,至少把学到的东西记录下来. 先说明一下 ...
- dijkstra算法matlab程序_编程习题课 | 用最短路算法为你的小地图导航
简介:路网拓扑的正确导入方式,运筹学算法的完整实战案例,最详细的代码讲解与分享. 引言:在研究路径选择和流量分配等交通问题时,常常会用到最短路算法.用最短路算法解决交通问题存在两个难点:一.算法的选择 ...
- 坐在马桶上看算法:Dijkstra最短路算法
[坐在马桶上看算法]算法7:Dijkstra最短路算法 上周我们介绍了神奇的只有五行的 ...
- 坐在马桶上看算法:只有五行的Floyd最短路算法
坐在马桶上看算法:只有五行的Floyd最短路算法 此算法由Robert W. Floyd(罗伯特·弗洛伊德)于1962年发表在"Communications of the ACM" ...
- 疯子的算法总结(八) 最短路算法+模板
Dijkstra:适用于权值为非负的图的单源最短路径,用斐波那契堆的复杂度O(E+VlgV) BellmanFord:适用于权值有负值的图的单源最短路径,并且能够检测负圈,复杂度O(VE) SPFA: ...
- Dijkstra 最短路算法(只能计算出一条最短路径,所有路径用dfs)
上周我们介绍了神奇的只有五行的 Floyd 最短路算法,它可以方便的求得任意两点的最短路径,这称为"多源最短路".本周来来介绍指定一个点(源点)到其余各个顶点的最短路径,也叫做&q ...
- lee最短路算法_Lee算法的解释:迷宫运行并找到最短路径
lee最短路算法 Lee算法是什么? (What is the Lee Algorithm?) The Lee algorithm is one possible solution for maze ...
- zuc算法代码详解_最短路算法-dijkstra代码与案例详解
引言 在研究路径选择和流量分配等交通问题时,常常会用到最短路算法.用最短路算法解决交通问题存在两个难点: 一.算法的选择和程序的编写.最短路算法有很多种改进算法和启发式算法,这些算法的效率不同,适用的 ...
最新文章
- sqlite-1.0.0源码执行的基本流程概述
- bootstrap 树形表格渲染慢_bootstrap-table-treegrid数据量较大时渲染太久了
- ASM元数据备份与恢复:md_backup和md_restore
- Windows 7 下 Node.js 连接 Oracle
- python编写代码时零_python – KeyError:运行打包代码时为0L
- [css] 头部设置meta也可以做到自适应为啥还要用rem?
- Could not open ServletContext resource [/WEB-INF/applicationContext.xml]”解决方案
- 多线程编程学习总结(转载)
- IDEA安装“Alibaba Java Coding Guidelines”插件
- CURL -w 参数详解
- ADC采样频率的计算
- diameter协议栈_Diameter协议摘要
- 2007软件英雄会暨CSDN社区英雄榜颁奖典礼邀请人员名单
- 计算机管理映像路径,windows任务管理器显示映像路径和命令行设置参考
- CCF 1158. 骰子游戏
- 环境变量使用与何时使用环境变量
- 如何在Joomla中创建一个漂亮的单页网站
- simulink 报错Derivative of state ‘1‘ in block ..... at time 0.0 is not finite.
- 那天,比尔・盖茨差点“砍掉”了这个 160 亿美元的项目:不运行 Windows,是种侮辱...
- cmos图像传感器简介
热门文章
- JavaScript实现计时器
- mysql整数转为2位小数_SQL整数转换成小数
- 随机数rand和srand的用法
- pointnet train 第十句correct = tf.equal(tf.argmax(pred, 1), tf.to_int64(labels_pl))
- AliCDN,盛开在云端的花朵
- 搜遍全网,终于找到一个适合新手入门的物联网教程
- nginx重启报找不到nginx.pid的解决方法
- python中的path的使用
- 《千手智能打铃》使用说明
- Windows环境下编译Airsim