一个我认为比较好的Spfa模板(使用邻接表和队列实现)
2015-05-16 22:02
162 查看
全局准备工作
Node定义
addEdge函数
Spfa主体
main中初始化
int N, X; //N为点数 X为源点 int head[MAXN]; //head[src]表示以head为出发点的邻接表表头在数组Adj中的位置,开始时所有元素初始化为-1 int nodeP; //在邻接表和指向表头的head数组中定位用的记录指针,开始时初始化为0 int dist[MAXN]; //储存到源节点的距离,在Spfa()中初始化 bool vis[MAXN]; //这里vis作inqueue解释会更好,出于习惯使用了vis来命名,在Spfa()中初始化
Node定义
struct Node { int v, w, next; }Adj[MAXM];v即vertex,这里意思相当于被指向的点to,w相当于weight,代表边权,next用来指向在Adj中下一个从相同src出发的边指向的点
addEdge函数
void addEdge(int src, int to, int weight) { Adj[nodeP].v = to; Adj[nodeP].w = weight; Adj[nodeP].next = head[src]; head[src] = nodeP++; }addEdge(a, b, w)作用是在数组Adj中留下一条记录了去向和边权的记录,且其next指向表中相同src指向的下一个点,同时更新了head表头
Spfa主体
void Spfa() { queue<int> que; int i; for(i = 1; i <= N; i++) { dist[i] = NIL; vis[i] = false; } dist[X] = 0; //X为源点 que.push(X); while(!que.empty()) { int now = que.front(); que.pop(); vis[now] = false; //从queue中退出 //遍历邻接表 for(i = head[now]; i != -1; i = Adj[i].next) { //在Adj中,相同src出发指向的顶点为从head[src]开始的一项,逐项使用next寻找下去,直到找到第一个被输 //入的项,其next值为-1 int to = Adj[i].v; if(dist[to] == NIL || dist[to] > dist[now] + Adj[i].w) { //松弛(RELAX)操作 dist[to] = dist[now] + Adj[i].w; if(!vis[to]) { //若被搜索到的节点不在队列que中,则把to加入到队列中去 vis[to] = true; que.push(to); } } } } }
main中初始化
int main() { memset(head, -1, sizeof(head)); ... while(...) { cin >> a >> b >> c; addEdge(a, b, c); } Spfa(); //结果已经储存在dist数组中 return 0; }有些人以为这个算法是Dijkstra,事实上Spfa和Dijkstra很像,只是他们维护的队列不同,Spfa维护的是一个初始只有源节点的队列,而Dijkstra要维护初始为所有顶点的队列。
相关文章推荐
- 【题目5】如何使用两个栈来实现一个队列
- C#基础之温习--使用列表和链表实现优一个先级队列
- 使用两个队列实现一个栈,使用两个栈实现一个队列!
- 使用俩个栈实现一个队列的功能
- 使用数组实现一个随机队列
- 使用两个队列实现一个栈,使用两个栈实现一个队列!
- 使用两个Stack类(JDK容器类库中的Stack类)实现一个队列类MyQueue,提供队列的入队列和出队列操作:enQueue和deQueue
- 使用两个队列实现一个栈,使用两个栈实现一个队列!
- 28. 微软面试题:使用多线程实现一个队列
- C++ 模板应用 实现一个Queue 队列
- 使用两个队列实现一个栈
- cc150:使用两个栈实现一个队列(两种方法比较)
- 纪念逝去的岁月——C++实现一个队列(使用类模板)
- Cracking coding interview(3.5)使用2个堆栈实现一个队列
- 最短路模板——dijkstra,SPFA(邻接表实现)
- 013使用两个栈实现一个队列(keep it up)
- 剑指offer_面试题7_用两个栈实现队列(让我熟悉了类模板的使用)
- 使用2个队列实现一个栈
- 算法导论 使用两个队列实现一个栈
- C++利用模板实现一个队列