题目来源:http://poj.org/problem?id=3268
本题需要用两次SPFA,来求解去和返回的最短时间。按测试样例,所画出的图,如下:
每次都是以X为源点,来进行松弛求解最短时间:
(1)以每个顶点的出边所构成的邻接表,然后求源点X到各个顶点的最短距离,这个最短距离,表示的就是,返回时从X到各个农场的最短时间。
(2)以每个顶点的入边当作出边所构成的邻接表,然后求出源点X到各个定点的最短距离,这个最短距离,表示的就是,每个农场到农场X的最短时间。
一般的求解源点到其他顶点的最短距离,所构建的邻接表都是由每个顶点的出边所构成的。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int INF = 10000000;
const int MAXN = 1010;
struct ArcNode//邻接表结构
{
int to;
int weight;
ArcNode* pNext;
ArcNode()
{
to = 0;
weight = 0;
pNext = NULL;
}
};
ArcNode* List[MAXN];// List与ReList分别为正向图和反向图
ArcNode* ReList[MAXN];
int dist[MAXN];
void SPFA(int n, int v0, int direction)//direction为:0表示正向图,1反向图
{
queue <int> Q;
bool inq[MAXN];//标志数组,记录顶点是否在队列中
int i, u;
for(i = 0; i <= n; ++i)
{
dist[i] = INF;
inq[i] = false;
}
dist[v0] = 0;
Q.push( v0 );
while( !Q.empty())
{
u = Q.front();
Q.pop();
inq[u] = false;
ArcNode* ptr = new ArcNode;
if(direction != 0)
ptr = List[u]->pNext;
else
ptr = ReList[u]->pNext;
while( ptr != NULL )
{
int v = ptr->to;
if(dist[v] > dist[u] + ptr->weight)//松弛操作
{
dist[v] = dist[u] + ptr->weight;
if( !inq[v] )
{
inq[v] = true;
Q.push( v );
}
}
ptr = ptr->pNext;
}
}
}
void Inser_List(int u, int v, int w)//邻接表的插入操作
{
ArcNode* ptr = new ArcNode;
ptr->to = v;
ptr->weight = w;
ptr->pNext = List[u]->pNext;
List[u]->pNext = ptr;
ptr = new ArcNode;
ptr->to = u;
ptr->weight = w;
ptr->pNext = ReList[v]->pNext;
ReList[v]->pNext = ptr;
}
void Destroy_List(int N)//释放链表
{
int i;
for(i = 0; i <= N; ++i)
{
ArcNode* ptr;
ptr = List[i];
while(ptr != NULL)
{
List[i] = ptr->pNext;
delete ptr;
ptr = List[i];
}
}
for(i = 0; i <= N; ++i)
{
ArcNode* ptr;
ptr = ReList[i];
while(ptr != NULL)
{
ReList[i] = ptr->pNext;
delete ptr;
ptr = ReList[i];
}
}
}
int main()
{
int N, M, src;
int u, v, w;
int i;
while(~scanf("%d %d %d", &N, &M, &src))
{
for(i = 0; i <= N; ++i)
{
List[i] = new ArcNode;
ReList[i] = new ArcNode;
}
for(i = 0; i < M; ++i)
{
cin>>u>>v>>w;
Inser_List(u, v, w);
}
int ans[MAXN], MaxTime = 0; //累加的最短时间以及最短时间的最大值
memset(ans, 0, sizeof(ans));
SPFA(N, src, 0);//正向求最短路
for(i = 1; i <= N; ++i)
if(i != src)//反向求最短路,并累加最短时间
ans[i] += dist[i];
SPFA(N, src, 1);
for(i = 1; i <= N; ++i)
{
if(i != src)
{
ans[i] += dist[i];
if(ans[i] > MaxTime)//在最短时间中取最大值
MaxTime = ans[i];
}
}
cout<<MaxTime<<endl;
Destroy_List(N);
}
return 0;
}