SPFA专题

来源:互联网 发布:全国安全网络知识竞赛 编辑:程序博客网 时间:2024/05/22 21:17

首先 SPFA 算法是用来求最短路径的,相比Dijastra  SPFA还可以处理权值为负数的情况,实际上这个算法在国际中并不被认可,但是它的确是一个高效的最短路算法,它是Bellman-Ford算法的优化版本,时间复杂度为O(kE),k的值一般情况下比较小,所以比较适合来求最短路径。

SPFA算法的思想

首先建立一个d数组来记录每个节点i到起点s的最短路径长度,将d数组所有初始值全部赋为正无穷(其实在写程序的时候,自己定义一个比较大的数INF然后都赋值成INF就好了)

创建一个队列,由于本人习惯使用STL中的queue队列,所以,本人的代码中会有queue出现。queue的基本操作:q.push(value):将元素value入队,无返回值;q.front():取出队列首部元素,有返回值;q.pop():弹出队列首部元素,无返回值;

将d[s]赋值成为0,并以节点s扩展更新与s相邻节点到s的最短距离,并将更新成功的节点入队,弹出s,并且每次用队列的首元素更新与这个元素相邻的节点的d[i]值,并将成功更新的节点加入队列。(这里要注意,有可能被更新成功的节点已经在队列中,这时就无需再次将其加入队列,只需将被成功更新并且没有在队列中的节点入队即可)并且使用队列首元素更新完成后将取出的队列首元素弹出队列,这样循环一直到队列为空的时候停止。

在这里举个例子吧:比如在一个图中,有1、2、3、4、5这5个节点,现在以1为起始点,1加入队列q,并记录1已经在队列中,1更新了2、3、4,那么就将2、3、4加入队列,(此时d[2]、d[3]、d[4]已经更新),将1弹出队列,并且设置1不在队列中,接下来取2更新,检索到了3、4、5,成功更新了4、5,,4无需再进队列,5进队列,弹出2,设置2不在队列中,再用3去更新,此时更新到了2,那么2再次进入队列,这样不断循环,直到q为空为止;

下面给出模板

#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <vector>#include <queue>#define maxn 1001#define INF 100000000using namespace std;struct edge{    int from,to,dist;    edge(int a,int b,int c):from(a),to(b),dist(c){};};vector<edge>edges;vector<int>f[maxn];int n,m,j,k,l;int d[maxn];bool v[maxn];//queue_visited[1001];int spfa(int s){//核心代码     memset(v,false,sizeof(v));    for(int i = 1;i <= n;++i){        d[i] = INF;    }    queue<int>q;    d[s] = 0;    v[s] = true;    q.push(s);    while(!q.empty()){        int x = q.front();        q.pop();        v[x] = 0;        for(int i = 0;i < f[x].size();++i){            edge o = edges[f[x][i]];            if(o.dist + d[x] < d[o.to]){                d[o.to] = o.dist + d[x];                if(!v[o.to]){                    v[o.to] = 1;                    q.push(o.to);                 }            }        }    }    return d[n];}int main(){    scanf("%d%d", &n, &m);    for(int i = 1;i <= m;++i){//链表存储         cin >> j >> k >> l;        edges.push_back(edge(j,k,l));        edges.push_back(edge(k,j,l));        int count = edges.size();        f[j].push_back(count-2);        f[k].push_back(count-1);      }    int ans = spfa(1);    cout<<ans<<endl;    return 0;}
下面给出例题

MPI Maelstrom
Time Limit: 1000MS Memory Limit: 10000KTotal Submissions: 8129 Accepted: 4988

Description

BIT has recently taken delivery of their new supercomputer, a 32 processor Apollo Odyssey distributed shared memory machine with a hierarchical communication subsystem. Valentine McKee's research advisor, Jack Swigert, has asked her to benchmark the new system.
``Since the Apollo is a distributed shared memory machine, memory access and communication times are not uniform,'' Valentine told Swigert. ``Communication is fast between processors that share the same memory subsystem, but it is slower between processors that are not on the same subsystem. Communication between the Apollo and machines in our lab is slower yet.''

``How is Apollo's port of the Message Passing Interface (MPI) working out?'' Swigert asked.

``Not so well,'' Valentine replied. ``To do a broadcast of a message from one processor to all the other n-1 processors, they just do a sequence of n-1 sends. That really serializes things and kills the performance.''

``Is there anything you can do to fix that?''

``Yes,'' smiled Valentine. ``There is. Once the first processor has sent the message to another, those two can then send messages to two other hosts at the same time. Then there will be four hosts that can send, and so on.''

``Ah, so you can do the broadcast as a binary tree!''

``Not really a binary tree -- there are some particular features of our network that we should exploit. The interface cards we have allow each processor to simultaneously send messages to any number of the other processors connected to it. However, the messages don't necessarily arrive at the destinations at the same time -- there is a communication cost involved. In general, we need to take into account the communication costs for each link in our network topologies and plan accordingly to minimize the total time required to do a broadcast.''

Input

The input will describe the topology of a network connecting n processors. The first line of the input will be n, the number of processors, such that 1 <= n <= 100.

The rest of the input defines an adjacency matrix, A. The adjacency matrix is square and of size n x n. Each of its entries will be either an integer or the character x. The value of A(i,j) indicates the expense of sending a message directly from node i to node j. A value of x for A(i,j) indicates that a message cannot be sent directly from node i to node j.

Note that for a node to send a message to itself does not require network communication, so A(i,i) = 0 for 1 <= i <= n. Also, you may assume that the network is undirected (messages can go in either direction with equal overhead), so that A(i,j) = A(j,i). Thus only the entries on the (strictly) lower triangular portion of A will be supplied.

The input to your program will be the lower triangular section of A. That is, the second line of input will contain one entry, A(2,1). The next line will contain two entries, A(3,1) and A(3,2), and so on.

Output

Your program should output the minimum communication time required to broadcast a message from the first processor to all the other processors.

Sample Input

55030 5100 20 5010 x x 10

Sample Output

35

#include <cstdio>#include <vector>#include <queue>#include <string>#include <string.h>#include <iostream>#include <sstream>#include <algorithm>using namespace std;int const MAX = 10005;int const inf = 1000000;struct Edge{    int u, v, w;    void edge(int a, int b, int c){        u = a;        v = b;        w = c;    }}e[MAX];vector<int> G[101];int n, dist[101];bool cmp(int a, int b){    return a > b;}int read_list(int a[101]){    string line;    getline(cin, line);    stringstream ss(line);    int i = 0;    char t[10];    while(ss >> t){        if(!strcmp(t, "x")){            a[i++] = -1;            continue;        }        stringstream sss(t);        int k;        sss >> k;        a[i++] = k;    }    return i;}void spfa(int s){    int vis[101];    for(int i = 1; i <= n; i++){         dist[i] = inf;         vis[i] = 0;    }    dist[1] = 0;    queue<int> q;    q.push(1);    vis[1] = 1;    while(!q.empty()){        int k = q.front();        q.pop();        vis[k] = 0;        for(int i = 0; i < G[k].size(); i++){            int tmp = e[G[k][i]].v;            int value = e[G[k][i]].w;            if(dist[k] + value < dist[tmp]){                 dist[tmp] = dist[k] + value;                if(!vis[tmp]){                    q.push(tmp);                    vis[tmp] = 1;                }            }        }    }}int main(){    int cnt = 0;    scanf("%d", &n);    getchar();    for(int i = 2; i <= n; i++){        int a[101];        int num = read_list(a);        for(int j = 0; j < num; j++){            if(a[j] != -1){                e[++cnt].edge(i, j + 1, a[j]);                //printf("%d %d %d %d\n", cnt, e[cnt].u, e[cnt].v, e[cnt].w);                G[i].push_back(cnt);                e[++cnt].edge(j + 1, i, a[j]);                //printf("%d %d %d %d\n", cnt, e[cnt].u, e[cnt].v, e[cnt].w);                G[j+1].push_back(cnt);            }        }    }    spfa(1);    sort(dist + 1, dist + n + 2, cmp);    printf("%d\n", dist[1]);    return 0;}


0 0
原创粉丝点击