题目:
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?
Input
Line 1: Three space-separated integers, respectively: N, M, and X
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.
Output
Line 1: One integer: the maximum of time any one cow must walk.
Sample Input
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
Sample Output
10
Hint
Cow 4 proceeds directly to the party (3 units) and returns via farms 1 and 3 (7 units), for a total of 10 time units.
代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAX 1005
#define NIL 1e9
int mp[MAX][MAX],dis[MAX],back_dis[MAX];
bool vis[MAX];
int Dijkstra(int n,int x)
{
int minx,flag;
for(int i = 1;i <= n;i++){
vis[i] = true;
back_dis[i] = mp[x][i];//代表从聚会地点返回各自农场的最短路径
dis[i] = mp[i][x];//从各自农场到聚会地点的最短路径
}
back_dis[x] = 0;
for(int i = 1;i <= n;i++){
minx = NIL;
for(int j = 1;j <= n;j++){
if(vis[j] && minx > back_dis[j]){
minx = back_dis[j];
flag = j;
}
}
vis[flag] = false;
for(int j = 1;j <= n;j++){
if(vis[j] && back_dis[flag] + mp[flag][j] < back_dis[j])
back_dis[j] = back_dis[flag] + mp[flag][j];
}
}
for(int i = 1;i <= n;i++) vis[i] = true;
dis[x] = 0;
for(int i = 1;i <= n;i++){
minx = NIL;
for(int j = 1;j <= n;j++){
if(vis[j] && minx > dis[j]){
minx = dis[j];
flag = j;
}
}
vis[flag] = false;
for(int j = 1;j <= n;j++){
if(vis[j] && dis[j] > dis[flag] + mp[j][flag])
dis[j] = dis[flag] + mp[j][flag];
}
}
int maxn = -1;
for(int i = 1;i <= n;i++)
maxn = max(maxn,dis[i] + back_dis[i]);
return maxn;
}
int main()
{
int N,M,X,a,b,c;
scanf("%d%d%d",&N,&M,&X);
for(int i = 0;i < MAX;i++){
for(int j = 0;j < MAX;j++){
if(i == j) mp[i][j] = 0;
else mp[i][j] = NIL;
}
}
for(int i = 0;i < M;i++){
scanf("%d%d%d",&a,&b,&c);
mp[a][b] = c; //有向图
}
int minx = Dijkstra(N,X);//传入农村总数和聚会地点
cout << minx << endl;
return 0;
}
这道题基本题意是给出n个点和m条边,接着是m条边,分别输入a,b,c,代表从牛从a到b需要花费c时间(注意这是有向图),现在n个点中除了用于聚会的x那个点其他点都有牛要到x来聚会,然后再走回去,他们都有一个参加聚会并且回来的最短时间,要求从这些最短时间里找出一个最大值输出。
由于这道题是要求多个不同点之间的最短路径,所以我就选择用floyd算法,结果直接超时,因为题目数据太大,floyd的复杂度过高,随后我就想到了使用Dijkstra算法,Dijkstra可以分为两部分,一部分是牛走到点x聚会的最短路径,还有一部分就是从x返回起点的最短路径。由于这是有向图,所以来的时候和返回的时候路径可能不一样。先来说返回远点的最短路径,这个比较好理解,就把x点看成是起点,其他点都当成终点,这和一般的Dijkstra没什么区别。还有一部分就是去x的最短路径,这种情况只需要在对边松弛的情况下换一下行列就可以了(其实就相当于是反向的求单源最短路径)。