spfa算法

poj 2449 k短路(A*+spfa)

我是研究僧i 提交于 2020-01-26 06:30:17
题目:就是求给出的两点之间的第k短的路,没有的话就输出-1 A*算法其实就是在搜索的时候有一个方向,计算出最可能是答案的解 /* F(p)=g(p)+h(p) g(p)为当前从s到p所走的长度,h(p)为从p到 t 的最短路的长度, 则F(p)的意义就是从s按照当前路径走到 p 后要走到终点 t 一共至少要走多远*/ #include<iostream> #include<cstdio> #include<queue> #include<cstring> using namespace std; const int maxx = 100010; const int inf = 0x3f3f3f3f; struct node { int f,g,v; }; bool operator < (node a,node b) { if(a.f==b.f)return a.g>b.g; return a.f>b.f; } struct edge { int v,next,w; }e1[maxx],e2[maxx]; int head1[maxx],head2[maxx],num=0; int n,m,s,t,k; int vis[1010],dis[1010]; void add(int u,int v,int w) { e1[++num].v=v;e1[num].w=w; e1[num]

spfa算法

丶灬走出姿态 提交于 2020-01-23 00:07:37
spfa算法是对bellman-ford算法的优化,bellman-ford算法遍历每一条边,不断的迭代更新。但是注意到,有许多边的值是不变的,也就是说不需要更新,所以spfa算法基于这一点进行优化,只有值变小的点才有机会去更新其他点。所以我们用一个队列来存储可以更新其他点的点。 1 1.初始化 2 while 队列不空 3 { 4 2.取队头; 5 3.标记不在队列中 6 4.更新其他点 7 } 1.初始化需要初始化dis数组为正无穷,将第一个点dis置为0,将第一个点加入队列,并标记在队列中。 2.当队列不空时取队头元素,并将其标记置为不在队列中。 3.需要注意的是spfa中的st数组是标记该点是否在队列中,与dijkstra算法中的st数组作用不同,dijkstra算法中的st数组是在出队时标记已经用过,所以只会标记一次。而spfa数组的元素是可以多次入队的。 4.由于spfa算法是bellman-ford算法的优化,所以spfa算法是可以处理带负权边的单源最短路算法,而dijkstra是只能处理正权边的单源最短路算法。 完整代码: 1 #include <cstring> 2 #include <iostream> 3 #include <algorithm> 4 #include <queue> 5 6 using namespace std; 7 8 const int

Dijkstra Floyed SPFA 辨析

蓝咒 提交于 2020-01-19 16:48:07
一、Dijkstra O(nlogn) 单源最短路径 这个算法加上堆优化之后还是非常推荐的 但是dijkstra有一些不足的地方 边权不能为负数 不能判断负环 二、SPFA 最大是 O(mn) 单源最短路径 这个算法其实还是非常玄学的 要是运气不好的话会到达O(mn) 所以 不好掌控时间复杂度 但是它也有一些得天独厚的优势 它可以有负权边 也可以判断负环 判断负环的方法: 如果一个顶点入队列的次数超过n次 说明该图中存在负环 三、Floyed O(n^3) 多源最短路径 这个算法跑的很慢 在n不大的情况下可以用用 但是它 可以算出任意两个点之间的最短路径 还是非常不错的 来源: https://www.cnblogs.com/akioi/p/12214003.html

SPFA算法——最短路径

感情迁移 提交于 2020-01-19 15:18:04
粗略讲讲SPFA算法的原理,SPFA算法是1994年西安交通大学段凡丁提出 是一种求单源最短路的算法 算法中需要用到的主要变量 int n; //表示n个点,从1到n标号 int s,t; //s为源点,t为终点 int d[N]; //d[i]表示源点s到点i的最短路 int p[N]; //记录路径(或者说记录前驱) queue <int> q; //一个队列,用STL实现,当然可有手打队列,无所谓 bool vis[N]; //vis[i]=1表示点i在队列中 vis[i]=0表示不在队列中 几乎所有的最短路算法其步骤都可以分为两步 1.初始化 2.松弛操作 初始化: d数组全部赋值为INF(无穷大);p数组全部赋值为s(即源点),或者赋值为-1,表示还没有知道前驱 然后d[s]=0; 表示源点不用求最短路径,或者说最短路就是0。 将源点入队;     (另外记住在整个算法中有顶点入队了要记得标记vis数组,有顶点出队了记得消除那个标记) 队列+松弛操作 读取队头顶点u,并将队头顶点u出队(记得消除标记);将与点u相连的所有点v进行松弛操作,如果能更新估计值(即令d[v]变小),那么就更新,另外,如果点v没有在队列中,那么要将点v入队(记得标记),如果已经在队列中了,那么就不用入队 以此循环,直到队空为止就完成了单源最短路的求解 SPFA可以处理负权边 定理:

最短路——spfa算法

╄→гoц情女王★ 提交于 2020-01-19 13:22:35
##算法功能   找最短路(最长路?) ##算法思想   用一个节点k更新节点i到节点j的最短路 ##邻接链表存储   基础而高效的图的存储方式   存的是单向边(无向边可以看成两条有向边) ##实现   维护节点i到源点s的最小值d[i]   用队列实现     维护队列z,       用visit[]记录一个点是否在队列     从源点开始进队列,每次弹出队头元素x,(标记visit[x]=0)     用它的最短路d[x]将与它相连的节点y的最短路d[y]更新     如果y不在队列(visit[y]==0),让y入队,记录(visit[y]=1)     直到队列为空,所有节点的d[]都已维护好 ##判断负环   若图中存在负环,则更新时一定不断地让负环上的节点入队,负环上的点一定会无数次入队,最终死循环   所以我们记录一个点入队的次数sum[],sum[i]在每次i入队时++,如果sum[i]贼大,贼大,证明有负环     贼大到多大呢?贼大到2*m(m是边数)就肯定死循环了     反正就是不能比2*m大(一共m条边,假设都与节点i相连,则i最多入队m次(当然不可能所有边都让i走一遍)(老师让sum[i]和m*2比较,不知道为啥那么大 1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4

香甜的黄油(SPFA)

女生的网名这么多〃 提交于 2020-01-16 03:34:41
香甜的黄油(SPFA) Description 农夫John发现做出全威斯康辛州最甜的黄油的方法:糖。把糖放在一片牧场上,他知道N(1<=N<=500)只奶牛会过来舔它,这样就能做出能卖好价钱的超甜黄油。当然,他将付出额外的费用在奶牛上。   农夫John很狡猾。像以前的Pavlov,他知道他可以训练这些奶牛,让它们在听到铃声时去一个特定的牧场。他打算将糖放在那里然后下午发出铃声,以至他可以在晚上挤奶。   农夫John知道每只奶牛都在各自喜欢的牧场(一个牧场不一定只有一头牛)。给出各头牛在的牧场和牧场间的路线,找出使所有牛到达的路程和最短的牧场(他将把糖放在那) Input 第一行: 三个数:奶牛数N,牧场数(2<=P<=800),牧场间道路数C(1<=C<=1450) 第二行到第N+1行: 1到N头奶牛所在的牧场号 第N+2行到第N+C+1行: 每行有三个数:相连的牧场A、B,两牧场间距离D(1<=D<=255),当然,连接是双向的 ==Output == 一行 输出奶牛必须行走的最小的距离和 Sample Input 3 4 5 2 3 4 1 2 1 1 3 5 2 3 7 2 4 3 3 4 5 样例图形 P2 P1 @ -- 1 -- @ C1 \ | \ \ | \ 5 7 3 \ | \ \ | \ C3 C2 @ -- 5 -- @ P3 P4 Sample

差分约束 + spfa + 最长路 [NOI1999] 01串

和自甴很熟 提交于 2019-12-05 17:56:13
https://blog.csdn.net/Bill_Yang_2016/article/details/53556021 题目描述   给定7个整数N,A0,B0,L0,A1,B1,L1,要求设计一个01串S=s1s2…si…sN,满足:   1.si=0或si=1,1<=i<=N;   2.对于S的任何连续的长度为L0的子串sjsj+1…sj+L0-1(1<=j<=N-L0+1),0的个数大于等于A0且小于等于B0;   3.对于S的任何连续的长度为L1的子串sjsj+1…sj+L1-1(1<=j<=N-L1+1),1的个数大于等于A1且小于等于B1;   例如,N=6,A0=1,B0=2,L0=3,A1=1,B1=1,L1=2,则存在一个满足上述所有条件的01串S=010101。 用 S 表示01序列的1的个数的前缀和,然后就可以利用题目所给的不等式以及前缀和本身存在的信息,写出不等式进行差分约束算法。 注意!用前缀和表示区间和的时候所使用的前缀和数组的 L 要减1 。 #include <bits/stdc++.h> using namespace std; const int maxn = 1e5+110; int n,a0,b0,l0,a1,b1,l1; int s[maxn]; int cnt; struct node{ int from,to,val,next;

0x60 图论

巧了我就是萌 提交于 2019-12-04 13:19:40
0x61 最短路 Dijkstra 最短路的经典做法之一,相比后面的 \(SPFA\) , \(Dij\) 的复杂度更低,更加的稳定 但是如果出现负环时, \(Dij\) 是不能用的 #include <bits/stdc++.h> #define PII pair< int , int > #define F first #define S second using namespace std; const int N = 10005 , M = 500005 , INF = 0x7f7f7f7f; int n , m , s ; int dis[N]; vector< PII > e[N]; bool vis[N]; set<PII> q; inline int read() { register int x = 0; register char ch = getchar(); while( ch < '0' || ch > '9' ) ch = getchar(); while( ch >= '0' && ch <= '9' ) { x = ( x << 3 ) + ( x << 1 ) + ch - '0'; ch = getchar(); } return x; } inline void add( int x , int y , int w ) { e[x].push

POJ2516 Minimum Cost(SPFA费用流 &amp;&amp; 将稠密大图拆成多个小图以加速)

匿名 (未验证) 提交于 2019-12-03 00:22:01
http://poj.org/problem?id=2516 感觉网络流的题目意思都挺难理解的。 有N个商店,每个商店都有K种相同物品,现要从M个供应商进货,问能否满足所有商店的进货要求,如果满足输出最小费用,否则输出-1. 输入如下: 第一行是N M K. 一个N*K矩阵,a[i][j]表示第i号店进第j种物品的数量。 一个M*K矩阵,b[i][j]表示第i号仓库储备第j种物品的数量。 K个N*M矩阵,第k个矩阵中第i行第j列品k表示从第j个仓库进第k种物品到第i号店的费用。 一开始的思路:每个店有k种物品,那么就拆成k个点;每个仓库有k种物品,那么也拆成k个点。对这N*K+M*K个点按要求连边跑费用流。而是否满足供应要求,只需看最大流是否满流即可。也就是看第一个N*K矩阵的矩阵和是否等于最大流。 敲完提交,发现运行错误,原来一开始邻接表的边数只给了1e4,而拆点后,需要(N*K )* (M*K)条边。调整了边数提交后,发现TLE。分析了下时间复杂度,想起SPFA费用流算法在稠密图上运行比较慢。 难道要换dijstra费用流?emmmmmmm,可以将一个稠密大图拆成多个小图,虽然小图依然是稠密图,但是减少的幅度是非常大的。从2500*2500到50*50.这样,只需建K次图,跑K遍SPFA费用流即可。 //1141ms 0.4MB #include <cstdio>

SPFA算法

匿名 (未验证) 提交于 2019-12-03 00:11:01
定义 SPFA 算法是 Bellman-Ford算法 的队列优化算法的别称,通常用于求含负权边的单源最短路径,以及判负权环。 原理 动态逼近法: 如果某个点进入队列的次数超过 N 次则存在负环。 实现 代码 #include<bits/stdc++.h> using namespace std; const int maxn=1005; const int inf=0x3f3f3f3f; struct node { int v,w; node(){} node(int a,int b) {v=a;w=b;} }; int n,m; vector<node> e[maxn]; void SPFA(int s); int main() { int i,u,v,w; scanf("%d%d",&n,&m); for(i=1;i<=m;i++) { scanf("%d%d%d",&u,&v,&w); e[u].push_back(node(v,w)); } SPFA(1); system("pause"); return 0; } void SPFA(int s) { int i,p,v,w,dis[maxn],vis[maxn]={0},cnt[maxn]={0}; queue<int> que; fill(dis,dis+maxn,inf); que.push(s); dis[s]=0