要求:n个顶点m条路组成的有向图,输出每个点到达第x个点再从第x个点返回出发点走的距离的最短距离中的最大值。
方法:dijkstra变形
1.从第x个点返回出发点的最短距离可以直接用dijkstra求出。
2.从出发点到第x个点的最短距离乍一看是n个最短路,简单推理一下:第i个点到第x个点的最短距离等于反向的第x个点到第i个点的最短距离,因此构建一个和第1步反向的图,用dijkstra求第x个点到所有点的最短路即可。正所谓反(边)反(所求方向)得正。
#include<iostream>
#include<stdio.h>
#include<queue>
#include<map>
#include<string.h>
#include<math.h>
#include<algorithm>
#define inf 0x3f3f3f3f
using namespace std ;
int n , m , x ;
int map1[1005][1005] ;
int map2[1005][1005] ;
int vis[1005] ;
int dis1[1005] ;
int dis2[1005] ;
void dijkstra()
{
int i , j , k ;
int min1 , temp ;
int ans = 0 ;
memset(vis , 0 , sizeof(vis)) ;
for(i = 1 ; i <= n ; i ++)
dis1[i] = map1[x][i] ;
dis1[x] = 0 ;
vis[x] = 1 ;
for(i = 1 ; i < n ; i ++)
{
min1 = inf ;
for(j = 1 ; j <= n ; j ++)
if(!vis[j] && dis1[j] < min1)
{
min1 = dis1[j] ;
temp = j ;
}
vis[temp] = 1 ;
for(j = 1 ; j <= n ; j ++)
dis1[j] = min(dis1[j] , dis1[temp] + map1[temp][j]) ;
}
memset(vis , 0 , sizeof(vis)) ;
for(i = 1 ; i <= n ; i ++)
dis2[i] = map2[x][i] ;
dis2[x] = 0 ;
vis[x] = 1 ;
for(i = 1 ; i < n ; i ++)
{
min1 = inf ;
for(j = 1 ; j <= n ; j ++)
if(!vis[j] && dis2[j] < min1)
{
min1 = dis2[j] ;
temp = j ;
}
vis[temp] = 1 ;
for(j = 1 ; j <= n ; j ++)
dis2[j] = min(dis2[j] , dis2[temp] + map2[temp][j]) ;
}
for(i = 1 ; i <= n ; i ++)
ans = max(ans , dis1[i] + dis2[i]) ;
printf("%d\n" , ans) ;
}
int main()
{
int i , j , k , p ;
int a , b , c ;
scanf("%d%d%d" , &n , &m , &x) ;
memset(map1 , inf , sizeof(map1)) ;
memset(map2 , inf , sizeof(map2)) ;
memset(dis1 , inf , sizeof(dis1)) ;
memset(dis2 , inf , sizeof(dis2)) ;
for(i = 0 ; i < m ; i ++)
{
scanf("%d%d%d" , &a , &b , &c) ;
map1[a][b] = c ;
map2[b][a] = c ;
}
dijkstra() ;
}