记ben最喜欢的SPFA
About SPFA
本文记录一些咱搞过的一些SPFA的瞎搞,并不是SPFA的入门教程
单源最短路径
每次依一个与队长有关的概率随机排序队列, cmp
函数直接写按
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int M = 5e5 + 10, N = 1e5 + 10;
struct node{
int nxt,v,w;
}g[M];
int head[N],tot,lgg;
void add(int u,int v,int w){
g[++tot].v=v;
g[tot].w=w;
g[tot].nxt=head[u];
head[u]=tot;
}
int n,m,dis[N],t[N],kkk;
bool cmp(int l,int r){
return dis[l]<dis[r]-kkk;
}
long long ans;
bool vis[N];
std::mt19937 rd(time(0));
int q[N*122];
void SPFA(int s){
int l=0,r=0;
for(int i=1;i<=n;i++){
dis[i]=1e9;
vis[i]=0;
}
dis[s]=0;
q[l]=s;
vis[s]=1;
while(l<=r){
if(rd()%(((r-l+1>>4)*5)+1)==0)sort(q+l,q+r+1,cmp);
int u=q[l++];
vis[u]=0;
for(int i=head[u];i;i=g[i].nxt){
int v=g[i].v,w=g[i].w;
if(dis[u]+w<dis[v]){
dis[v]=dis[u]+w;
if(!vis[v]){
if(l>1) q[--l]=v;
else q[++r]=v;
vis[v]=1;
}
}
}
}
}
int s;
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n>>m>>s;
for(int i=1;i<=m;i++){
int u,v,w;
cin>>u>>v>>w;
add(u,v,w);
kkk+=w;
}
kkk=log2(kkk);
SPFA(s);
for(int i=1;i<=n;i++)
cout<<dis[i]<<" ";
}
johnson
这个其实更扯蛋
排序函数改一下,改成按
容错大概设为
#include<bits/stdc++.h>
const signed M = 1e4 + 10, N = 1e4 + 10;
int kkk;
#define int long long
using namespace std;
struct node{
int nxt,v,w;
}g[M];
int head[M],tot,lgg;
void add(int u,int v,int w){
g[++tot].v=v;
g[tot].w=w;
g[tot].nxt=head[u];
head[u]=tot;
}
int n,m,dis[N],t[N];
bool cmp(int l,int r){
return abs(dis[l])-abs(dis[r])<-kkk*2;
}
std::mt19937 rd(time(0));
long long ans;
bool vis[N];
bool down(){
int s=0;
stack<int> q;
for(int i=1;i<=n;i++){
dis[i]=1e9;
}
dis[s]=0;
q.push(s);
vis[s]=1;
t[s]++;
while(!q.empty()){
int u=q.top();
q.pop();
vis[u]=0;
for(int i=head[u];i;i=g[i].nxt){
int v=g[i].v,w=g[i].w;
if(dis[u]+w<dis[v]){
dis[v]=dis[u]+w;
if(!vis[v]){
q.push(v);
vis[v]=1;
t[v]++;
}
}
if(t[v]>n){
return 0;
}
}
}
return 1;
}
int q[101010];
void SPFA(int s){
int l=0,r=0;
for(int i=1;i<=n;i++){
dis[i]=1e9;
vis[i]=0;
}
dis[s]=0;
q[l]=s;
vis[s]=1;
while(l<=r){
if(rd()%(((r-l+1)*5)+1)==0)sort(q+l,q+r+1,cmp);
int u=q[l++];
vis[u]=0;
for(int i=head[u];i;i=g[i].nxt){
int v=g[i].v,w=g[i].w;
if(dis[u]+w<dis[v]){
dis[v]=dis[u]+w;
if(!vis[v]){
if(l>1)q[--l]=v;
else q[++r]=v;
vis[v]=1;
}
}
}
}
}
signed main(){
// freopen("P5905_11.in", "r", stdin);
// freopen("sb.txt", "w", stdout);
cin>>n>>m;
for(int i=1;i<=n;i++){
add(0,i,0);
}
for(int i=1;i<=m;i++){
int u,v,w;
cin>>u>>v>>w;
add(u,v,w);
kkk+=w;
}
kkk=abs(kkk)/n/m;
if(!down()){
cout<<-1;
return 0;
}
for(int i=1;i<=n;i++){
SPFA(i);
for(int j=1;j<=n;j++){
ans+=dis[j]*j;
}
cout<<ans<<"\n";
ans=0;
}
}
糖果(hack SPFA version)
奇妙,我们注意到这道题排序的意义不大,于是直接改随机化,调参,发现怎么着都会 T
然后我们发现只要带负环我们的复杂度就很容易寄,没有负环是飞快的
那卡时即可
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int M = 5e5 + 10, N = 1e6 + 10;
struct node{
int nxt,v,w;
}g[M];
int head[N],tot,lgg;
void add(int u,int v,int w){
g[++tot].v=v;
g[tot].w=w;
g[tot].nxt=head[u];
head[u]=tot;
}
int n,m,dis[N],t[N],kkk,tmer;
long long ans;
bool vis[N];
int in[114514];
std::mt19937 rd(time(0));
int q[N*12];
bool SPFA(int s){
int l=0,r=0;
for(int i=1;i<=n;i++){
dis[i]=INT_MAX;
vis[i]=0;
}
dis[s]=0;
q[l]=s;
vis[s]=1;
while(l<=r){
if(tmer>23550000)return 1;
// if((double)(clock()-F)/1000>940) return 1;
if(rd()%((((r-l+1)>>3)*53)+1)==0 and rd()%2==0){
int ysuperman=(l+r)>>1;
random_shuffle(q+ysuperman,q+r);
random_shuffle(q+l,q+(r+ysuperman)/2);
}
int u=q[l++];
vis[u]=0;
for(int i=head[u];i;i=g[i].nxt){tmer++;
int v=g[i].v,w=g[i].w;
if(dis[u]+w<dis[v]){
dis[v]=dis[u]+w;
in[v]=in[u]+1;
if(in[v]>n) return 1;
if(!vis[v]){
if(l>1)q[--l]=v;
else q[++r]=v;
vis[v]=1;
}
}
}
}
return 0;
}
int s,k;
signed main(){
srand(time(NULL));
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n>>k;
for (int i = 1, x, a, b; i <= k; i++) {
cin>>x>>a>>b;
if (x == 1) {
add(a, b, 0);
add(b, a, 0);
}
if (x == 2) add(a, b, -1),kkk--;
if (x == 3) add(b, a, 0);
if (x == 4) add(b, a, -1),kkk--;
if (x == 5) add(a, b, 0);
}
for (int i = 1; i <= n; i++) add(0, i, -1);
if(SPFA(0)){
cout<<-1;
return 0;
}
int ans=0;
for(int i=1;i<=n;i++)
ans+=dis[i];
cout<<-ans;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理