spfa算法

spfa的魔改方法

北慕城南 提交于 2020-03-11 07:40:21
spfa的魔改方法 ( \(update\) \(on\) \(2019/8/13\) ) 参考文献: spfa的玄学优化和Hack方法 学图论,你真的了解最短路吗? ETO组织成员 的题解小合集系列 题外话: 关于这篇博客的题目,我想了几个(光速逃……: 关于BellmanFord转生变成spfa的那些事 欢迎来到效率至上主义的OI图论 RE:从零开始的图论生活 能跑网格图,还能卡过菊花图,这样的spfa你喜欢吗 某科学的队优spfa 我的无优化spfa果然有问题 进入正题: 先来说一下 \(spfa\) 吧, \(spfa\) 的全称是 \(Shortest\) \(Path\) \(Fastest\) \(Algorithm\) ,其实就是 \(Bellman\) - \(Ford\) 算法加上一个队列优化。 其时间复杂度并不稳定,最快可以达到 \(O(1)\) ,最慢会被卡成 \(Bellman\) - \(Ford\) 的 \(O(nm)\) 今天就来总结一下学到的 \(spfa\) 的各种魔改: 前置:读入优化 由于毒瘤出题人很有可能会卡时间,所以我们需要读优(输出优化不一定) 标准代码:(随用随复制) inline int read() { int fu=1,x=0;char o=getchar(); while(o<'0'||o>'9'){if(o=='-')fu=

差分约束系统 + spfa(A - Layout POJ - 3169)

萝らか妹 提交于 2020-03-04 07:44:45
题目链接: https://cn.vjudge.net/contest/276233#problem/A 差分约束系统,假设当前有三个不等式 x- y <=t1 y-z<=t2 x-z<=t3 我们可以将第一个式子和第二个式子结合起来,就变成了x-z<= t1+t2 ,然后x-z的最大差值就是min(t1+t2,t3)(因为要使得最终结果都满足两个不等式) 然后求最小的过程(求差最大),就可以通过最短路的算法实现。 题目大意:给你n代表有n头牛,然后ml和md,接下来ml行,每行有三个数u v w代表u和v之间的距离最多是w,接下来md行,每行有三个数,代表u v 之间的距离最少是w,然后问你第一个牛和第n个牛最远可以相差多少,如果是无穷远输出-2.如果没有满足的情况,输出-1,否则输出dis【n】。 具体思路:我们可以将题目条件转换为不等式进行求解,对于第一种情况,也就是ml的时候,我们可以转成如下式子 posU-posV < = w 。然后我们就可以连一条边,u->v (权值是w),对于第二种情况,我们转化的式子是posU-posV>=w,我们需要将这个式子转换成和第一种形式相同的,所以两边同乘-1,就变成了 posV-posU<=-w,然后就是建边就可以了。 AC代码: 1 #include<iostream> 2 #include<cstring> 3 #include

邻接表(spfa模版)

可紊 提交于 2020-02-17 04:51:29
http://www.cnblogs.com/tonghao/p/4708661.html//数组模拟 邻接表只是储存图的方法,要求最短路还是要用其他算法。SPFA迪杰斯特拉等等算法。 #include<stdio.h> #include<iostream> #include<stdlib.h> #include<queue> #include<algorithm> #include<string.h> #define inf 0x3f3f3f using namespace std; bool vis[2005]; int dis[2005]; int T,N; struct node { int v,w; struct node*next; }*h[2005]; void LA(int u,int v,int w) { struct node *p=(struct node *)malloc(sizeof(struct node)); // p->u=u; p->v=v; p->w=w; p->next=h[u]; h[u]=p; } void spfa(int s) { queue<int>Q; memset(vis,false,sizeof(vis)); Q.push(s); dis[s]=0; while(!Q.empty()){ int u=Q.front(); Q

图论-spfa算法判断负环

大兔子大兔子 提交于 2020-02-12 00:27:00
原理 若存在负环,则迭代玩所有点后边数>=图中点的个数,根据抽屉原理,若edge>=point->图中应当有point+1个点,与point个点矛盾,所以存在负环. 例题 给定一个n个点m条边的有向图,图中可能存在重边和自环, 边权可能为负数。 请你判断图中是否存在负权回路。 输入格式 第一行包含整数n和m。 接下来m行每行包含三个整数x,y,z,表示存在一条从点x到点y的有向边,边长为z。 输出格式 如果图中存在负权回路,则输出“Yes”,否则输出“No”。 数据范围 1≤n≤2000, 1≤m≤10000, 图中涉及边长绝对值均不超过10000。 输入样例: 3 3 1 2 -1 2 3 4 3 1 -4 输出样例: Yes # include <cstring> # include <iostream> # include <algorithm> # include <queue> using namespace std ; const int N = 2010 , M = 10010 ; int n , m ; int h [ N ] , w [ M ] , e [ M ] , ne [ M ] , idx ; int dist [ N ] , cnt [ N ] ; bool st [ N ] ; void add ( int a , int b , int c ) {

HDU1217:Arbitrage(SPFA)

£可爱£侵袭症+ 提交于 2020-02-10 13:27:56
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1217 题目大意 在每种钱币间进行各种交换,最后换回自己如果能赚,那么就Yes,否则No 注意应为有负权所以dijsktra在这里行不通了可以用国产的spfa算法,可比bfs。 我的AC代码 #include<iostream> #include<cstdio> #include<cstring> #include<map> #include<queue> using namespace std; map<string,int> mat; int n,m; char str[100],s1[100],s2[100]; double trip[30][30],dis[30]; int main(void) { int spfa(int src); int i,j,ans=1; double w; while(scanf("%d",&n)==1&&n) { mat.clear(); for(i=1;i<=n;i++) { for(j=1;j<=n;j++) { if(i==j) trip[i][j]=1; else trip[i][j]=0; } } for(i=1;i<=n;i++) { scanf("%s",str); mat[str]=i; } scanf("%d",&m);

hdu 1217 Arbitrage (spfa算法)

心不动则不痛 提交于 2020-02-10 13:25:15
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1217 题目大意:通过货币的转换,来判断是否获利,如果获利则输出Yes,否则输出No。 这里介绍一个STL中的map容器去处理数据, map<string,int>V,M; 现在我目前的理解是将字符串转换成数字,然后就是根据spfa的模板找最短路了。。哇哈哈( ⊙o⊙ )哇 1 #include <iostream> 2 #include <cstdio> 3 #include <map> 4 #include <queue> 5 #include <cstring> 6 using namespace std; 7 int n,a; 8 double Map[35][35]; 9 const int INF=9999; 10 map<string,int>V; 11 12 int spfa() 13 { 14 queue<int>q; 15 double node[35]= {0}; 16 int inq[35]= {0}; 17 node[1]=1; 18 inq[1]=1; 19 q.push(1); 20 while (!q.empty()) 21 { 22 int s=q.front(); 23 q.pop(); 24 for (int i=1; i<=n; i++) 25

【模板】Spfa判负环

牧云@^-^@ 提交于 2020-02-07 21:53:21
【模板】Spfa判负环 给定一个n个点m条边的有向图,图中可能存在重边和自环, 边权可能为负数。 请你判断图中是否存在负权回路。 输入格式 第一行包含整数n和m。 接下来m行每行包含三个整数x,y,z,表示存在一条从点x到点y的有向边,边长为z。 输出格式 如果图中存在负权回路,则输出“Yes”,否则输出“No”。 数据范围 1 ≤n≤ 2000 , 1 ≤m≤ 10000 , 图中涉及边长绝对值均不超过 10000 。 输入样例: 3 3 1 2 - 1 2 3 4 3 1 - 4 输出样例: Yes 前言:如果你不了解Spfa算法,请先看这篇文章: 【模板】Spfa 好了,Spfa判负环的原理十分简单,思路就是在Spfa的基础上加一个 cnt 数组来判断一个点是否形成负环 推荐看的Blog: 【模板】Spfa 【模板】Floyd 【模板】Dijkstra 【模板】Bellman_Ford 具体代码如下: # include <bits/stdc++.h> using namespace std ; const int N = 2010 , M = 10010 ; int n , m , h [ N ] , w [ M ] , e [ M ] , ne [ M ] , idx ; int dist [ N ] , cnt [ N ] ; bool st [ N ] ; void

AcWing 851. spfa求最短路

馋奶兔 提交于 2020-02-05 23:40:12
给定一个n个点m条边的有向图,图中可能存在重边和自环, 边权可能为负数。 请你求出1号点到n号点的最短距离,如果无法从1号点走到n号点,则输出impossible。 数据保证不存在负权回路。 输入格式 第一行包含整数n和m。 接下来m行每行包含三个整数x,y,z,表示存在一条从点x到点y的有向边,边长为z。 输出格式 输出一个整数,表示1号点到n号点的最短距离。 如果路径不存在,则输出”impossible”。 数据范围 1≤n,m≤105, 图中涉及边长绝对值均不超过10000。 输入样例: 3 3 1 2 5 2 3 -3 1 3 4 输出样例: 2 难度: 简单 时/空限制: 1s / 64MB 总通过数: 1492 总尝试数: 2479 来源: 模板题 算法标签 # include <iostream> # include <cstdio> # include <cstring> # include <algorithm> # include <queue> using namespace std ; const int N = 100010 ; typedef pair < int , int > PII ; int n , m ; int dist [ N ] ; int h [ N ] , w [ N ] , e [ N ] , ne [ N ] , idx ;

最短路 SPFA()

拜拜、爱过 提交于 2020-01-30 01:26:03
  SPFA是用队列处理Bellman-Ford算法,效率很高。但他并不稳定。 1 #include<bits/stdc++.h> 2 using namespace std; 3 4 const int inf = 0x3f3f3f3f; 5 const int num = ???; 6 struct edge{ 7 int from, to, w;//边:起点from(其实没有用到),终点to,权值(距离)w 8 edge(int a, int b, int c){from=a; to=b; w=c;} 9 }; 10 vector<edge>e[num];//第i个节点连接的所有边 11 int n, m; 12 int dis[num];//从规定起点到点i的距离 13 int pre[num];//记录路径 14 15 //打印路径 16 void print_path(int s, int t){ 17 if(s == t){printf("%d",s); return ;} 18 print_path(s, pre[t]); 19 printf("->%d",t); 20 } 21 22 int spfa(int s){ 23 bool inq[num];//标记节点i是否在队列中 24 int neg[num];//判断负圈 25 //初始化 26 for(int

差分约束系统详解

随声附和 提交于 2020-01-29 17:27:08
前言 差分约束系统是一种特殊的N元一次不等式组,不等式组的每一个不等式称为一个约束条件。通过不等式的变形,可以通过最短路算法对差分约束系统进行求解。 相关定义 约束条件:一个满足 ​ 的不等式称为一个约束条件 差分约束系统:一个由若干个约束条件构成的N元一次不等式组称为一个差分约束系统 性质 $i,j\in[1,n]$,$k\in [1,m]$ $n_k\in R$ 观察约束条件的通式$a_i-a_j\leq n_k$,移项得$a_i\leq a_j+n_k$,是不是和最短路转移中的三角形不等式$d_y\leq d_x+edeg_i$很像?(明明是一模一样)。因此,我们可以将每个约束条件$a_i-a_j\leq n_k$看作一条从$j$连向$i$的权值为$n_k$的有向边,利用最短路算法进行求解。由于$n_k$可能为负数,因此要用SPFA进行求解(当然,dijkstra算法经过一番乱搞也是可以实现的)。 如果题目给出的约束条件是形如$a_i-a_j\geq n_k$,要怎么办呢?有两种办法,一是原样插入,跑最长路;二是将其变形为$a_j-a_i\leq -n_k$,将它看作一条从$i$连向$j$的权值为$-n_k$的有向边,还是跑最短路。 接下来会对差分约束系统的实现进行系统地讲解。在判断差分约束系统的可行性时需要判断负环,因此接下来会先讲解判定负环的方法。 负环 定义 环