前置:
免责声明:我自己看了这个博客后突发奇想,如有雷同纯属巧合
Using the Shortest Path Faster Algorithm to find a negative cycle. | KonaeAkira's blog
优化过程:
我的优化思路跟这个博客基本一样,具体可跳转链接查看
但这个博客中他通过DFS来提前判环
众所周知,floyd判环算法(即龟兔赛跑算法)可以用来快速判环
那我把DFS换成floyd岂不更快 Σ(っ °Д °;)っ
思路总结:
++增添计时器+floyd判环++
代码:
cycle()是floyd判环,
cpp
#pragma GCC optimize(2)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int N=2e3+5,M=1e4+5;
int n,m,d[N],h[N],e[M],ne[M],w[M],idx,cnt[N];
bool vis[N];
int pre[N];
void init(){
idx=0;
memset(h,-1,sizeof(h));
}
void add(int a,int b,int c){
e[idx]=b;
w[idx]=c;
ne[idx]=h[a];
h[a]=idx++;
}
bool cycle(int u){
int slow=u,fast=pre[u];
do{
if (pre[slow]==-1 || pre[fast]==-1 || pre[pre[fast]]==-1){
return false;
}
slow=pre[slow];
fast=pre[pre[fast]];
}while (slow!=fast);
return true;
}
bool spfa(){
memset(vis,0,sizeof(vis));
memset(cnt,0,sizeof(cnt));
memset(d,0,sizeof(d));
memset(pre,-1,sizeof(pre));
int step=0;
queue<int> q;
for (int i=1;i<=n;i++){
q.push(i);
vis[i]=true;
}
while (!q.empty()){
int now=q.front();
q.pop();
vis[now]=false;
for (int i=h[now];i!=-1;i=ne[i]){
int j=e[i];
if (d[j]>d[now]+w[i]){
pre[j]=now;
d[j]=d[now]+w[i];
cnt[j]=cnt[now]+1;
if (cnt[j]>=n){
return true;
}
if (++step>=(n<<1)){
if (cycle(j)){
return true;
}
step=0;
}
if (!vis[j]){
q.push(j);
vis[j]=true;
}
}
}
}
return false;
}
int main(){
init();
scanf("%d%d",&n,&m);
for (int i=0,a,b,c;i<m;i++){
scanf("%d%d%d",&a,&b,&c);
add(a,b,c);
}
if (spfa()){
puts("Yes");
}else{
puts("No");
}
return 0;
}
效果:
在Acwing上亲测比朴素SPFA快了50倍,比stack替换版快了1.2~1.4倍