读书人

poj 1511-spfa

发布时间: 2012-08-15 16:57:17 作者: rapoo

poj 1511----spfa

这道题目有点长,看了半天才看懂啥意思。

就是有n个车站,m条路线,每条路线有一个价格。

要求从起始站到每一站,然后再从每一站回去,求最少的钱数。

看起来就是最短路径的问题,就是求单源点到其他各点的最但距离(票价),然后建个反向图,求的返回的钱数。加起来就行了。

最短路径很多方法,Dijkstra算法,Bell-ford算法,floyd-washall,以及本题目用的spfa算法。

由于数据比较大,Dijkstra算法 (o(n^2)) floyd-washall(o(n^3))肯定会超时。

其实spfa比Dijkstra算法还要简单,代码更少,就是维护一个队列,队列里面放着可能经过的点,知道队列为空。

注意要用邻接表保存图,邻接矩阵会超内存的。

代码:

#include <stdio.h>#include <stdlib.h>#include <string.h>#define nMax 1000010#define eMax 10000010#define inf 1000000010struct EDGE{int v,w,next;}edge[nMax], reEdge[nMax];int nEdge[nMax], nReEdge[nMax];int n, m, queue[eMax];__int64 dis[nMax], sum;bool vis[nMax];void edgeInit(){for (int i = 1; i <= n; ++ i){nEdge[i] = 0;nReEdge[i] = 0;}}void spfaInit(){for (int i = 1; i <= n; ++ i){dis[i] = inf;vis[i] = false;}}void spfa(int * nEdge, EDGE * edge){spfaInit();int head = 0, tail = 1;dis[1] = 0;queue[0] = 1;while (head < tail){int u = queue[head];vis[u] = true;int p = nEdge[u];while (p != 0){int v = edge[p].v, w = edge[p].w;if (dis[v] > dis[u] + w){dis[v] = dis[u] + w;if (!vis[v]){vis[v] = true;queue[tail] = v;tail ++;}}p = edge[p].next;}vis[u] = false;head ++;}for (int i = 1; i <= n; ++ i){sum += dis[i];}}int main(){int t;scanf("%d", &t);while (t --){scanf("%d%d", &n, &m);edgeInit();for (int i = 1; i <= m; ++ i){int u, v, w;scanf("%d%d%d", &u, &v, &w);edge[i].v = v;edge[i].w = w;edge[i].next = nEdge[u];nEdge[u] = i;reEdge[i].v = u;reEdge[i].w = w;reEdge[i].next = nReEdge[v];nReEdge[v] = i;}sum = 0;spfa(nEdge, edge);spfa(nReEdge, reEdge);printf("%I64d\n", sum);}return 0;}


读书人网 >其他相关

热点推荐