题意:一群奶牛开party,在X奶牛家开,所有奶牛都要去,找出每头奶牛到X和从X回家的最短路径和,输出路程最长的奶牛走的路,图是单向图;
回家的路好求,单源最短路,Dijkstra算法就可以了,而每头奶牛daoX的最短路不好求,但逆向思考一下,把图改成逆向图,还是X到其他点的单源最短路;
之前一直用邻接矩阵存图,刚学会用邻接表(也有叫链式前向星的,实在没明白两者有啥区别)存图,写一下代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <queue>
#define INF 0x3f3f3f3f
#define MAX1 100005
#define MAX2 1005
using namespace std;
int head[MAX2], rehead[MAX2]; //head X->others; rehead others->X;(边的起点,head[1]=2,以1为起点的边是第二条边)
int N, M, X;
int dis[MAX2], redis[MAX2]; //same with up;
int cnt, recnt; //所存边的条数;
bool vis[MAX2]; //标记已用边;
struct Edge{ //结构体存边;
int v; //边的重点;
int w; //边的权;
int next; //同起点的下一条边;
}edge[MAX1], reedge[MAX1]; //
void add_edge(int u, int v, int w){//向edge中存边;
edge[cnt].v=v; //终点;
edge[cnt].w=w; //权重;
edge[cnt].next=head[u]; //下一条边的起点;
head[u]=cnt++; //以u为起点的边是第几条;
}
void add_reedge(int u, int v, int w){//same with up;
reedge[recnt].v=v;
reedge[recnt].w=w;
reedge[recnt].next=rehead[u];
rehead[u]=recnt++;
}
void Dijkstra(int s){
memset(dis,INF,sizeof(dis));//点s到其他点的距离初始化为INF;
memset(vis,false,sizeof(vis));//所有点均为标记,初始化为false;
int i, j, k;
dis[s]=0; //s->s距离为零;
for(i=head[s]; i!=-1; i=edge[i].next){//以s为起点的边;
j=edge[i].v;
dis[j]=edge[i].w;;
}
for(i=1; i<=N; i++){ //借助每个点松弛一遍;
int _min=INF;
for(j=1; j<=N; j++){
if(!vis[j] && dis[j]<_min){//找到距离s点最近的点;
_min=dis[j];
k=j;
}
}
vis[k]=true; //已经用过的点标记一下,避免重复使用;
int z; //k点是需要借助的松弛点;
for(z=head[k]; z!=-1; z=edge[z].next){//借助以每个以k为起点的边松弛一下,直到以k为起点的边用完,即next指向-1;
int to=edge[z].v;
if(dis[to]>dis[k]+edge[z].w){//if s直接到to的距离大于通过k松弛的距离,就改变dis[to]的值;
dis[to]=dis[k]+edge[z].w;
}
}
}
}
void reDijkstra(int s){ //逆向存图X到其他点最短路;
memset(redis,INF,sizeof(redis));
memset(vis,false,sizeof(vis));
int i, j, k;
redis[s]=0;
for(i=rehead[s]; i!=-1; i=reedge[i].next){
j=reedge[i].v;
redis[j]=reedge[i].w;;
}
for(i=1; i<=N; i++){
int _min=INF;
for(j=1; j<=N; j++){
if(!vis[j] && redis[j]<_min){
_min=redis[j];
k=j;
}
}
vis[k]=true;
int z;
for(z=rehead[k]; z!=-1; z=reedge[z].next){
int to=reedge[z].v;
if(redis[to]>redis[k]+reedge[z].w){
redis[to]=redis[k]+reedge[z].w;
}
}
}
}
int main(){
cnt=recnt=0;
scanf("%d%d%d",&N,&M,&X);
memset(head,-1,sizeof(head));
memset(rehead, -1, sizeof(rehead));
while(M--){
int u, v, w;
scanf("%d%d%d",&u,&v,&w);
add_edge(u, v, w); //正向存图;
add_reedge(v, u, w); //逆向存图;
}
Dijkstra(X);
reDijkstra(X);
int _max=-1;
for(int i=1; i<=N; i++){
if(_max<dis[i]+redis[i])
_max=dis[i]+redis[i];
}
printf("%d\n",_max);
return 0;
}