题目链接:http://poj.org/problem?id=1511
题目大意:给出n个点和n条有向边,求所有点到源点1的来回最短路之和(保证每个点都可以往返源点1)
解题思路:这个数据范围太大,明显的不能用floyd,dijstra,bellman-ford这些算法,用spfa的话也不能用邻接矩阵存,因为点太多了,所以采用spfa的邻接表存储搞定稍微有点注意的地方是,来回之和只需要将所有的边反向再从1到所有点求最短路就是他们的最短回路,而且这个题
由于数据很大,所以最大值 inf 要设置很大。
#include <cstdio>
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
#define maxn 1000010
#define inf 0xFFFFFFFF
int n, m;
int head[2][maxn], vis[maxn];
long long sum, dis[maxn]; //数据要大点
struct node
{
int to, w, next;
}edge[2][maxn];
//国产算法核心代码,queue 实现
void SPFA(int a)
{
int v, i, b;
memset(vis, 0, sizeof(vis));
for(int i = 1; i <= n; i++)
dis[i] = inf;
queue<int>q;
q.push(1);
vis[1] = 1;
dis[1] = 0;
while(!q.empty())
{
v = q.front();
q.pop();
vis[v] = 0;
for(i = head[a][v]; i != -1; i = edge[a][i].next)
{
b = edge[a][i].to;
if(dis[b] > dis[v]+edge[a][i].w)
{
dis[b] = dis[v]+edge[a][i].w;
if(!vis[b])
{
vis[b] = 1;
q.push(b);
}
}
}
}
}
int main()
{
int Case, a, b, w, i;
cin>>Case;
while(Case--)
{
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++)
{
head[0][i] = -1;
head[1][i] = -1;
}
// 用静态邻接表( 又称为链式前向星 )存储,效率很高。
for(int i = 0; i < m; i++)
{
scanf("%d%d%d", &a, &b, &w);
edge[0][i].to = b;
edge[0][i].w = w;
edge[0][i].next = head[0][a];
head[0][a] = i;
// 构造反图
edge[1][i].to = a;
edge[1][i].w = w;
edge[1][i].next = head[1][b];
head[1][b] = i;
}
sum = 0;
SPFA(0);
for(int i = 1; i <= n; i++)
sum += dis[i];
SPFA(1);
for(int i = 1; i <= n; i++)
sum += dis[i];
printf("%I64d\n", sum);
}
return 0;
}
转载自 http://blog.csdn.net/wangjian8006/article/details/7871158