题目描述
农场有N(1≤N≤1000)个牛棚,每个牛棚都有1只奶牛要参加在X牛棚举行的奶牛派对.共有M(1≤M≤100000)条单向路连接着牛棚,第i条踣需要Ti的时间来通过.牛们都很懒,所以不管是前去X牛棚参加派对还是返回住所,她们都采用了用时最少的路线.那么,用时最多的奶牛需要多少时间来回呢?
输入格式
第1行:三个用空格隔开的整数.
第2行到第M+1行,每行三个用空格隔开的整数:Ai, Bi,以及Ti.表示一条道路的起点,终点和需要花费的时间.
输出格式
唯一一行:一个整数: 所有参加聚会的奶牛中,需要花费总时间的最大值.
回去的最少时间好算,就是单源多汇最短路,dijkstra跑一遍就可以了。但是过来的最少时间呢?
问题变成了多源最短路。但不要急着敲Floyd,可以注意到虽然是多源,但是是单汇。如果是从汇点往源点跑的话就可以用dijkstra了。所以在原图的基础上建个反图,过来的时候跑反图,回去的时候跑正图,时间复杂度为O((N+M)*N),加堆优化就是O((N+M)logN)
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#define maxn 1001
#define maxm 100001
using namespace std;
struct graph{
struct edge{
int to,dis,next;
edge(){}
edge(const int &_to,const int &_dis,const int &_next){
to=_to,dis=_dis,next=_next;
}
}e[maxm];
int head[maxn],k;
inline void init(){ memset(head,-1,sizeof head); }
inline void add(const int &u,const int &v,const int &w){
e[k]=edge(v,w,head[u]),head[u]=k++;
}
}a,b;
int dis[maxn],ans[maxn];
bool vis[maxn];
int n,m,s;
priority_queue< pair<int,int>,vector< pair<int,int> >,greater< pair<int,int> > > q;
inline int read(){
register int x(0),f(1); register char c(getchar());
while(c<'0'||'9'<c){ if(c=='-') f=-1; c=getchar(); }
while('0'<=c&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
inline void dijkstra(const graph &g){
memset(dis,0x3f,sizeof dis),memset(vis,false,sizeof vis);
q.push(make_pair(0,s)),dis[s]=0;
while(q.size()){
int u=q.top().second; q.pop();
if(vis[u]) continue; vis[u]=true;
for(register int i=g.head[u];~i;i=g.e[i].next){
int v=g.e[i].to;
if(dis[v]>dis[u]+g.e[i].dis){
dis[v]=dis[u]+g.e[i].dis;
q.push(make_pair(dis[v],v));
}
}
}
}
int main(){
a.init(),b.init();
n=read(),m=read(),s=read();
for(register int i=1;i<=m;i++){
int u=read(),v=read(),w=read();
a.add(u,v,w),b.add(v,u,w);
}
dijkstra(a);
for(register int i=1;i<=n;i++) ans[i]+=dis[i];
dijkstra(b);
for(register int i=1;i<=n;i++) ans[i]+=dis[i];
int mmax=0;
for(register int i=1;i<=n;i++) mmax=max(mmax,ans[i]);
printf("%d\n",mmax);
return 0;
}