看到题目的数据量,就知道要用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 : [email protected] * 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; }