http://poj.org/problem?id=3268
N只母牛(起始地点不同)要去X这个地方,给出有向图,要求求出他们到x后并且返回(不一定原路,有向图)的路程最大的母牛(算的是来回),
其中他们走到x和从x返回走的路径均是最短的。
思路:
从x到每个点的最短路径还算好求。直接Dijkstra即可
但是从每个点到x呢?
难道要n次Dijkstra?或者floyd?
不,那样效率太低了!
一个方法是进行矩阵转置,然后再来一次Dijkstra即可。
为什么这样可以?对于有向图,本来是从n个点到x的,你转置一下相当于x到n个点了。
很巧妙吧?
#include<cstdio> #include<algorithm> using namespace std; const int MAXN=1010; const int INF=99999; int map[MAXN][MAXN]; int n,m,x; void map_reverse() { for(int i=1;i<=n;i++) for(int j=1;j<i;j++) swap(map[i][j],map[j][i]); } void dijkstra(int dis[]) { bool vis[MAXN]={0}; int cur=x; vis[cur]=true; dis[cur]=0; for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) if(map[cur][j]!=INF && map[cur][j] +dis[cur] < dis[j]) dis[j]=map[cur][j] +dis[cur]; int mini=INF; for(int j=1;j<=n;j++) if(!vis[j] && dis[j] < mini) mini=dis[cur=j]; vis[cur]=true; } } int main() { while(~scanf("%d%d%d",&n,&m,&x)) { for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) map[i][j]=INF; } for(int i=0;i<m;i++) { int a,b,t; scanf("%d%d%d",&a,&b,&t); map[a][b]=t; } int dis1[MAXN],dis2[MAXN]; for(int i=1;i<=n;i++) dis1[i]=dis2[i]=INF; dijkstra(dis1); map_reverse(); dijkstra(dis2); int ans=-1; for(int i=1;i<=n;i++) { if(dis1[i]==INF || dis2[i]==INF) continue; int temp=dis1[i]+dis2[i]; if(temp > ans) ans=temp; } printf("%d\n",ans); } return 0; }