一座城市为无向图带权图,一号节点为披萨餐厅的位置,有\(k\)我的定披萨,按时间前后顺序给出定披萨的时间\(s_i\),地点\(u_i\)以及这我的的披萨在哪一个时间作好\(t_i\)。问在全部配送方案中,全部人的等待时间的最大值最小是多少?配送顺序彻底按照先来先服务的原则。node
首先求\(n\)次\(Dijkstra\)求出任意两点间配送所须要的最短路程时间是多少。而后二分答案\(t\),即假定全部人的等待时间的最大值为\(t\),而后枚举验证便可。ios
由于配送顺序按照先来先服务的原则,因此不一样方案间惟一的区别就是:从餐厅出发后连续配送多少个订单后回到餐厅。定义数组\(d[i]\)表示配送第\(i\)我的的订单,并回到餐厅须要的最短期为\(d[i]\)。对于第\(i\)个订单,要么连续配送\(1,2,\dots,i\),要么连续配送\(2,3,\dots,i\),要么\(\dots\),要么直接配送\(i\),时间取最小值便可。因此直接\(O(n^2)\)枚举便可。数组
#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #include<queue> using namespace std; #define int long long #define maxn 1005 #define maxm 5005 #define INF 1e15 namespace Dijkstra{ struct node{ int v,w,next; node(){} node(int v,int w,int next=-1):v(v),w(w),next(next){} bool operator <(const node&a)const{ return w>a.w; } }g[maxm<<1]; int head[maxn],cnt=0; bool vis[maxn]; void init(){ memset(head,-1,sizeof(head));cnt=0; } void addedge(int u,int v,int w){ g[cnt]=node(v,w,head[u]); head[u]=cnt++; } int dis[maxn][maxn]; void Run(int r,int n){ for(int i=0;i<=n;i++) dis[r][i]=INF;dis[r][r]=0; memset(vis,0,sizeof(vis)); priority_queue<node>q; q.push({r,0}); while(!q.empty()){ node now=q.top();q.pop(); int u=now.v; if(vis[u]) continue; vis[u]=1; for(int i=head[u];~i;i=g[i].next){ int v=g[i].v,w=g[i].w; if(!vis[v]&&dis[r][u]+w<dis[r][v]){ dis[r][v]=dis[r][u]+w; q.push({v,dis[r][v]}); } } } } }; int s[maxn],u[maxn],t[maxn],dp[maxn];//第i我的的最短配送时间为dp[i] bool check(int mid,int k){ for(int i=1;i<=k;i++) dp[i]=INF;dp[0]=0; for(int i=0;i<k;i++){ int len=0/*配送路程*/,Min=INF/*最晚能在何时离开餐厅,同一批的取最小值*/,st=dp[i]/*离开餐厅的时间*/; for(int j=i+1;j<=k;j++){ if(j==i+1) len+=Dijkstra::dis[1][u[j]]; else len+=Dijkstra::dis[u[j-1]][u[j]]; st=max(st,t[j]); Min=min(Min,mid-(len-s[j])); int delay=len+st-s[j]; if(delay<=mid&&st<=Min) dp[j]=min(dp[j],st+len+Dijkstra::dis[u[j]][1]); //在知足条件的状况下,才更新答案 else break; } } return dp[k]<INF; //若是最后一个订单都配送到了,则知足条件 } signed main(){ ios::sync_with_stdio(false); cin.tie(0);Dijkstra::init(); int n,m;cin>>n>>m; for(int i=1;i<=m;i++){ int u,v,w;cin>>u>>v>>w; Dijkstra::addedge(u,v,w); Dijkstra::addedge(v,u,w); } for(int i=1;i<=n;i++){ Dijkstra::Run(i,n); //求任意两个节点之间的最短路径 } int q;cin>>q; for(int i=1;i<=q;i++){ cin>>s[i]>>u[i]>>t[i]; } int left=0,right=1e15,mid,ans=INF; while(left<=right){ //二分答案 mid=(left+right)>>1; if(check(mid,q)){ right=mid-1; ans=min(ans,mid); }else{ left=mid+1; } } cout<<ans<<endl; cin.get(),cin.get(); return 0; }