您的位置:首页 > 其它

最短路——SPFA

2016-01-30 10:30 405 查看
bellman算法有太多冗余的松弛操作,SPFA利用队列省去了冗余的讨论,时间复杂度约为O(KE)k约为2,E为边数。

代码如下:

#include<cstdio>
#include<iostream>
#include<queue>
const int  inf=10000000;
using namespace std;
queue<int>q;
int n,m,x,y,map[105][105],vis[105],dist[105];    // vis[i]记录i是否在队列中;
void input(){
int p,q,i,j,t;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(i!=j)map[i][j]=inf;
for(i=1;i<=m;i++){
scanf("%d%d%d",&p,&q,&t);
map[p][q]=t;
}
scanf("%d%d",&x,&y);
}
void SPFA(){
int i,j;
for(i=1;i<=n;i++)dist[i]=inf;    //初始化
dist[x]=0;
q.push(x);
vis[x]=true;
while(!q.empty()){
int cur=q.front();    //取队首元素
q.pop();
vis[cur]=false;      //及时修正标记
for(i=1;i<=n;i++)
if(dist[cur]+map[cur][i]<dist[i]){
dist[i]=dist[cur]+map[cur][i];
if(!vis[i]){vis[i]=true;q.push(i);}
}
}
printf("%d",dist[y]);
}
int main(){
input();
SPFA();
}


根据算法原理,每个点最多只会入队n次,如过某个点入队达到n+1(这是血的教训)次,那么该图中有负权回路。

以下是利用边存储的结构体形式的SPFA,并且带有负权回路判定的代码

last[x] 表示以x为起点的最后一条边

next[x]表示和x边同起点的下一条边,0表示没有了

edge是存储边的数组

<pre name="code" class="cpp">#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#include<vector>

#define LL long long
#define CLEAR(XXX) memset((XXX),0,sizeof(XXX))
using namespace std;

const LL inf=1000000000000LL;
const int maxn=1005,maxm=100005;

inline void _read(int &x){
char ch=getchar(); bool mark=false;
for(;!isdigit(ch);ch=getchar())if(ch=='-')mark=true;
for(x=0;isdigit(ch);ch=getchar())x=x*10+ch-'0';
if(mark)x=-x;
}
struct Edge{
int from,to,w;
Edge(int from,int to,int w):from(from),to(to),w(w){}
};
struct SPFA{
int  n,m;
vector<Edge> edge;
int last[maxm],Next[maxm];
LL dist[maxn];
int cnt[maxn];
bool vis[maxn];
void init(int n){
this->n = n;
m=0;
CLEAR(last);  CLEAR(Next);
edge.clear();
edge.push_back(Edge(0,0,0));
}
void add_edge(int from,int to,int dist){
edge.push_back(Edge(from,to,dist));
m=edge.size()-1;
Next[m]=last[from];
last[from]=m;
}
bool solve(int s){
int i;
CLEAR(vis); CLEAR(cnt);
for(i=1;i<=n;i++) dist[i]=inf;
dist[s]=0;
vis[s]=true;cnt[s]++;
queue <int> q;
q.push(s);
while(!q.empty()){
int x=q.front();
q.pop();vis[x]=false;  //及时修改标记
for(i=last[x];i;i=Next[i]){
Edge& e=edge[i];
if(dist[e.from]+e.w<dist[e.to]){
dist[e.to]=dist[e.from]+e.w;
if(!vis[e.to]){
cnt[e.to]++;  //统计入队次数,判断负权回路
if(cnt[e.to]==n+1)return false;
q.push(e.to) ;
vis[e.to]=true;
}
}
}
}
return true;
}
void answer(){
for(int i=1;i<=n;i++)
if(dist[i]>=inf)printf("NoPath\n");
else printf("%I64d\n",dist[i]);
}
};
int main(){
SPFA spfa;
int n,m,s,i,from,to,dist;
_read(n);_read(m);_read(s);
spfa.init(n);
for(i=1;i<=m;i++){
_read(from);_read(to);_read(dist);
spfa.add_edge(from,to,dist);
}
if(spfa.solve(s))spfa.answer();
else printf("negetive loop");
return 0;
}



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: