//看一下bellman_ford:其实他就是通过不断的松弛构造一颗以源点为根的最短路径树,原算法中第i次松弛结束后一定能生成从树根到结点长度不超过i的最短距的点中的最短距离(说的好绕哟)
//注意,没优化的bellman并不保证松弛i次后每一个距离都是路径长度为i的最短的,因为它松弛边的时候无序,可能得到>i次的松弛结果
//所以使用spfa标记点的距离,,还有需要注意的是我们要开二维数组标记,,因为显然我们无法确定一个更短权 和 一个更短路 对它所邻接点更新时谁会使得最终结果更优
#include <iostream> #include <string> #include <map> #include <vector> #include <memory.h> #include <cstdio> #include <cmath> #include <algorithm> using namespace std; const int MAX=1005,INF=1<<30; struct State{ int dis,num; }; int n,m,u[MAX*10],v[MAX*10],w[MAX*10], d[MAX][MAX],first[MAX],next[MAX*10]; map<string,int> mymap; bool inq[MAX][MAX]; State q[MAX*MAX],temp,out; void bellman_ford(const int &len){ memset(inq,0,sizeof(inq)); int front=1,rear=1; int U,V,W,minVal=INF, sta=0,end=n-1,dis; for(int i=0;i<n;i++) for(int j=0;j<=len;j++){ if(!i) d[i][j]=0; else d[i][j]=INF; } temp.num=sta; temp.dis=0; inq[temp.num][temp.dis]=1; q[rear++]=temp; while(front<rear){ out=q[front++]; U=out.num; dis=out.dis; for(int e=first[U];e!=-1;e=next[e]){ V=v[e]; W=w[e]; if(d[V][dis+1]>d[U][dis]+W &&dis+1<=len){ d[V][dis+1]=d[U][dis]+W; if(!inq[V][dis+1]){ inq[V][dis+1]=1; temp.num=V; temp.dis=dis+1; q[rear++]=temp; } } } } for(int i=0;i<=len;i++){ if(d[end][i]<minVal) minVal=d[end][i]; } if(minVal!=INF) cout<<"Total cost of flight(s) is $"<<minVal<<endl; else cout<<"No satisfactory flights"<<endl; } int main() { freopen("i.txt","r",stdin); int nCase,t,num=0,Q; string s,su,sv; cin>>nCase; while(nCase--){ memset(first,-1,sizeof(first)); if(num++) cout<<endl; cout<<"Scenario #"<<num<<endl; mymap.clear(); cin>>n; for(int i=0;i<n;i++){ cin>>s; mymap[s]=i; } cin>>m; for(int i=0;i<m;i++){ cin>>su>>sv; u[i]=mymap[su]; v[i]=mymap[sv]; cin>>w[i]; next[i]=first[u[i]]; first[u[i]]=i; } cin>>Q; while(Q--){ cin>>t; if(t<0) t=0; if(t>n) t=n; bellman_ford(t+1); } } return 0; }