spfa優化 SLF LLL
2013.10.23 更新
之前寫的時候不知道在想什麼,整理模板時才發現寫挫了,現在重發一個
SPFA 是按照 FIFO 的原則更新距離的, 沒有考慮到距離標號的作用. 實現中 SPFA 有兩個非常著名的優化: SLF 和 LLL.
SLF: Small Label First 策略.
實現方法是, 設隊首元素為 ,
隊列中要加入節點
,
在
時加到隊首而不是隊尾, 否則和普通的 SPFA 一樣加到隊尾. 這可以用個優先級隊列維護
LLL: Large Label Last 策略.
實現方法是, 設隊列
中的隊首元素為
,
距離標號的平均值為
,
每次出隊時, 若
,
把
移到隊列末尾, 如此反複, 直到找到一個
使
,
將其出隊.
/** 複雜度分析: 普通SPFA km kmax=n 不適合稠密圖 一般為2 優先級隊列 加入節點複雜度logn 節點數太多時適得其反,對於特殊數據速度略小於普通spfa 對於隨機圖效果很好 手動模擬SLF,LLL 複雜度低於優先級隊列,最壞情況與普通SPFA持平 */ #define Maxn 100010//最大點數 #define Maxm 400010//最大邊數,無向圖要建雙向邊 int w[Maxm],u[Maxm],next[Maxm],cnt; int first[Maxn],havein[Maxn];//havin為入隊次數 long long d[Maxn];//距離 int n; bool in[Maxn];//隊中標誌 inline void add(int vn,int un,int wn){//鄰接表存儲 u[cnt]=un;w[cnt]=wn;next[cnt]=first[vn];first[vn]=cnt++; } struct node{ int v,dd; node(int &a):v(a),dd(d[a]){}; bool operator< (const node& a)const{ return dd>a.dd; } }; priority_queue<node> q; //利用優先級隊列SLF和LLL bool spfa(int s){ int i,now,ne,t; memset(in,0,sizeof(in)); memset(havein,0,sizeof(havein)); for(i=0;i<n;i++)d[i]=INF; //memset(d,0x3f,sizeof(d)); d[s]=0;in[s]=1;q.push(s); while(!q.empty()){ now=q.top().v;q.pop(); if(!in[now])continue; in[now]=0; for(i=first[now];~i;i=next[i]){ ne=u[i]; if(d[ne]<=(t=d[now]+w[i]))continue; d[ne]=t; in[ne]=1; q.push(ne); if(++havein[ne]>n)return 0;//判斷有無負環 } } return 1;//返回1為正常,0為有負環 } #define M 200000 //手動模擬 int q[M]; bool spfa(int s){ int i,now,ne,t; memset(in,0,sizeof(in)); memset(havein,0,sizeof(havein)); memset(d,0x3f,sizeof(d)); int l,r,len;l=r=len=0; long long sum=0; d[s]=0;in[s]=havein[s]=1; q[r++]=s;len++; while(l!=r){ now=q[l++]; if(l==M)l=0; if(d[now]*len>sum){//LLL q[r++]=now; if(r==M)r=0; continue; } len--; sum-=d[now]; in[now]=0; for(i=first[now];~i;i=Next[i]){ ne=u[i]; if(d[ne]<=(t=d[now]+w[i]))continue; d[ne]=t; if(in[ne])continue; in[ne]=1; if(t<=d[q[l]]){ //SLF if(--l<0)l=M-1; q[l]=ne; } else{ q[r++]=ne; if(r==M)r=0; } len++; sum+=t; if(++havein[ne]>n)return 0; } } return 1;//返回1為正常,0為有負環 } void init()//邊初始化 { cnt=0; memset(first,-1,sizeof(first)); }
最後更新:2017-04-02 00:06:49