首页 > 代码库 > SPFA(模板)

SPFA(模板)

转载请注明出处:http://blog.csdn.net/u012860063

#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <climits>
#include <malloc.h>
#include <ctype.h>
#include <queue>
#include <stack>
#include <vector>
#include <deque>
#include <set>
#include <map>
#include <iostream>
#include <algorithm>
using namespace std;
#define pi acos(-1.0)
#define INF 0xffffff
#define N 1005
#define M 2005
int n,m,k,Edgehead[N],dis[N];
struct
{
	int v,w,next;
}Edge[2*M];
bool vis[N];
void Addedge(int u,int v,int w)
{
	Edge[k].next = Edgehead[u];
	Edge[k].w = w;
	Edge[k].v = v;
	Edgehead[u] = k++;
}
int SPFA( int start)
{
	queue<int>Q;
	for(int i = 1 ; i <= n ; i++ )
		dis[i] = INF;
	dis[start] = 0;
	memset(vis,false,sizeof(vis));
	Q.push(start);
	while(!Q.empty())//直到队列为空
	{
		int u = Q.front();
		Q.pop();
		vis[u] = false;
		for(int i = Edgehead[u] ; i!=-1 ; i = Edge[i].next)//注意
		{
			int v = Edge[i].v;
			int w = Edge[i].w;
			if(dis[v] > dis[u] + w)
			{
				dis[v] = dis[u]+w;
				if( !vis[v] )//防止出现环,也就是进队列重复了  
				{
					Q.push(v);
					vis[v] = true;
				}
			}
		}
	}
	return dis[n];
}
int main()
{
	int u,v,w;
	while(~scanf("%d%d",&m,&n))//n为目的地
	{
		k = 1;
		memset(Edgehead,-1,sizeof(Edgehead));
		for(int i = 1 ; i <= m ; i++ )
		{
			scanf("%d%d%d",&u,&v,&w);
			Addedge(u,v,w);//双向链表
			Addedge(v,u,w);//双向链表
		}
		int s = SPFA(1);//从点1开始寻找最短路
		printf("%d\n",s);
	}
	return 0;
}
/*详情见http://blog.csdn.net/u012860063/article/details/24497211
对于负环,我们可以证明每个点入队次数不会超过V,所以我们可以开个数组来记录每个点的入队次数,

如果超过V则表示其出现负环,(SPFA无法处理带负环的图)算法结束,此模板貌似不需要考虑重边*/

有时候正向寻找不对,我们不防反向寻找一下(生活亦如此)!