题目大意:穿越虫洞可以回到过去(时间--)所以能不能让时间倒流呢,就是判断有没有负权回路这次尝试用SPFA算法,也可以复习一下链式前向星
准备工作,队列q,spfa算法得有点就在于这个队列,相对于bellman_ford算法来讲,spfa算法并不是盲目得去做松弛操作,而是对队列中的点进行松弛,只要队列不空就可以从队列中拿出点来做松弛,也就死只有先松弛了队列中得点(边松弛边添加)才能去松弛其余的更远得点!
dis,vis经典数组
time数组时用来判断某个点松弛得次数得(进队列得次数)
id【】以及tot时用来链式前向星得
tot就相当于链子得每一个节点只增不减
id用来连接每一个有关得节点
#include <iostream> #include <cstdio> #include <string.h> #include <queue> #define inf 0x3f3f3f3f using namespace std; const int maxn = 5050; queue<int> q; int dis[maxn]; int vis[maxn]; int time[maxn]; int id[maxn]; struct node{ int to; int cost; int pre; }e[maxn]; int tot;
看看链式前向星,对于当前节点我记录他的数据,然后寻找相关得点的下标(前一个)id[from]然后更新id[from]
void add(int from,int to,int cost) { e[tot].to = to; e[tot].cost = cost; e[tot].pre = id[from]; id[from] = tot++; }
算法前得初始化
void init(int n) { tot = 0; for(int i = 1;i <= n;i++) { id[i] = -1; dis[i] = inf; vis[i] = time[i] = 0; } // memset(id,-1,sizeof(id)); // memset(dis,inf,sizeof(dis)); // memset(vis,0,sizeof(vis)); // memset(time,0,sizeof(time));
spfa算法
准备工作做好了,明白了,难得就不再spfa算法本身了
bool spfa(int s,int n) { vis[s] = 1; dis[s] = 0; q.push(s); time[s]++; while(q.size()) { int now = q.front();q.pop(); for(int i = id[now];~i;i = e[i].pre) { int to = e[i].to; if(dis[to] > dis[now] + e[i].cost) { dis[to] = dis[now] + e[i].cost; if(!vis[to])//表示这个点不在队列中 { vis[to] = 1; q.push(to); if(++time[to] > n)return true; } } } vis[now] = 0; } return false; }