看到题目的数据量,就知道要用SPFA了。问题在于是否要对每个顶点求SPFA呢?事实上不是的。如果用farm表示正常的距离矩阵,transform表示farm装置后的矩阵。对farm求x的SPFA可以得出x到各个顶点的最短距离,也就是返回时的最短距离,那各个顶点到到x的最短距离呢?因为transform是farm的转置矩阵,即farm[a][b]=transform[b][a]=len,可以知道在transform中每条边的方向相反了,长度不变,这时对transform的x求SPFA,就可以得到各个顶点到X的最短距离了。如果仍有疑问的同学可以自己画图演示一下。
/*******************************************************************************
* Author : Neo Fung
* Email : neosfung@gmail.com
* Last modified : 2011-09-14 22:03
* Filename : POJ3268 Silver Cow Party.cpp
* Description :
* *****************************************************************************/
// POJ3268 Silver Cow Party.cpp : Defines the entry point for the console application.
//
// #include "stdafx.h"
// #define DEBUG
#include <fstream>
#include <stdio.h>
#include <string.h>
#include <string>
#include <memory.h>
#include <queue>
#define MAX 1100
#define maxint 1<<30
using namespace std;
int farm1[MAX][MAX],farm2[MAX][MAX],path1[MAX],path2[MAX],visit[MAX];
queue<int> myqueue;
void fspa(int (*farm)[MAX],int source,int n,int *path)
{
for(int i=1;i<=n;++i)
path[i]=maxint,visit[i]=0;
path[source]=0;
visit[source]=1;
myqueue.push(source);
while(!myqueue.empty())
{
int temp=myqueue.front();
myqueue.pop();
visit[temp]=0;
for(int i=1;i<=n;++i)
if(path[i]-path[temp]>farm[temp][i])
{
path[i]=path[temp]+farm[temp][i];
if(!visit[i])
myqueue.push(i),visit[i]=1;
}
}
}
int main(void)
{
#ifdef DEBUG
freopen("data.txt","r",stdin);
#endif
int n,m,x,a,b,len;
while(scanf("%d %d %d",&n,&m,&x)!=EOF)
{
for(int i=1;i<=n;++i)
{
for(int j=i+1;j<=n;++j)
farm1[i][j]=farm1[j][i]=farm2[i][j]=farm2[j][i]=maxint;
farm1[i][i]=farm2[i][i]=0;
}
for(int i=0;i<m;++i)
{
scanf("%d %d %d",&a,&b,&len);
if(farm1[a][b]>len)
farm1[a][b]=farm2[b][a]=len;
}
fspa(farm1,x,n,path1);
fspa(farm2,x,n,path2);
int maxlen=0;
for(int i=1;i<=n;++i)
if(maxlen-path1[i]<path2[i])
maxlen=path1[i]+path2[i];
printf("%d\n",maxlen);
}
return 0;
}