One cow from each of N farms (1 ≤ N ≤ 1000) conveniently numbered 1..N is going to attend the big cow party to be held at farm #X (1 ≤ X ≤ N). A total of M (1 ≤ M ≤ 100,000) unidirectional (one-way roads connects pairs of farms; road i requires Ti (1 ≤ Ti ≤ 100) units of time to traverse.
Each cow must walk to the party and, when the party is over, return to her farm. Each cow is lazy and thus picks an optimal route with the shortest time. A cow's return route might be different from her original route to the party since roads are one-way.
Of all the cows, what is the longest amount of time a cow must spend walking to the party and back?
Lines 2.. M+1: Line i+1 describes road i with three space-separated integers: Ai, Bi, and Ti. The described road runs from farm Ai to farm Bi, requiring Ti time units to traverse.
4 8 2 1 2 4 1 3 2 1 4 7 2 1 1 2 3 5 3 1 2 3 4 4 4 2 3
10
题意:
位于N个牛场的N头牛要去X牛场开party,完事之后再各回各家,牛们都比较懒,
因此来回都走最短路线(同一条路来回用时不一定相同),要求妹头牛来回所花时间最大值
思路:
此题为最短路问题,但问题是
去的时候是多源到单源的最短路问题(所有牛从家去X牛场)---------》寸边关系时反向存放,转化为单源到多源的最短路问题-----》Dijkstra算法
回来时候是单源到多源的最短路问题(所有牛从X牛场回各家)-------》常规Dijkstra算法
AC代码:
#include<stdio.h>
#include<string.h>
#define MAX 1005
#define Inf 0x3f3f3f3f
using namespace std;
int e1[MAX][MAX],e2[MAX][MAX]; //e1记录所有牛去的路线图的反方向 e2记录回的时候的方向(即已知方向)
int dis1[MAX],dis2[MAX]; //dis1记录去时所花的时间 dis2记录回时所花时间
int n,m,x;
void Dijkstra(int k,int dis[] );
int main(){
scanf("%d%d%d",&n,&m,&x);
memset(e1,Inf,sizeof(e1)); //memset 可以把数组初始化为0,-1,0x3f3f3f3f(为无限大)
memset(e2,Inf,sizeof(e2));
int i;
for(i=1;i<=n;i++)
e2[i][i]=e1[i][i]=0;
while(m--){
int a,b,t;
scanf("%d%d%d",&a,&b,&t); //去的时候反向存
if(t<e1[b][a]) e1[b][a]=t;
if(t<e2[a][b]) e2[a][b]=t;
}
Dijkstra(1,dis1);
Dijkstra(2,dis2);
int max=0;
for(i=1;i<=n;i++){
int s=dis1[i]+dis2[i]; //来回时间花最多的
max=max>s?max:s;
}
printf("%d\n",max);
return 0;
}
void Dijkstra(int k,int dis[] ){ //当k为1时是去时代最短路径问题,k为2时是回时的最短路径问题
int i,j;
for(i=1;i<=n;i++)
if(k==1) dis[i]=e1[x][i];
else dis[i]=e2[x][i];
int book[MAX];
memset(book,0,sizeof(book));
book[x]=1;
for(i=1;i<=n;i++){ //Dijkstra算法的核心操作
int min=Inf;
int u;
for(j=1;j<=n;j++){
if(!book[j]&&dis[j]<min){
min=dis[j];
u=j;
}
}
book[u]=1;
if(k==1) //松弛操作
for(j=1;j<=n;j++){
if(e1[u][j]<Inf){
if(dis[j]>dis[u]+e1[u][j]){
dis[j]=dis[u]+e1[u][j];
}
}
}
else
for(j=1;j<=n;j++){
if(e2[u][j]<Inf){
if(dis[j]>dis[u]+e2[u][j]){
dis[j]=dis[u]+e2[u][j];
}
}
}
}
}