TT 的旅行日记 Week7作业B题
題目:
眾所周知,TT 有一只魔法貓。
今天他在 B 站上開啟了一次旅行直播,記錄他與魔法貓在喵星旅游時的奇遇。 TT 從家里出發,準備乘坐貓貓快線前往喵星機場。貓貓快線分為經濟線和商業線兩種,它們的速度與價錢都不同。當然啦,商業線要比經濟線貴,TT 平常只能坐經濟線,但是今天 TT 的魔法貓變出了一張商業線車票,可以坐一站商業線。假設 TT 換乘的時間忽略不計,請你幫 TT 找到一條去喵星機場最快的線路,不然就要誤機了!
輸入:
輸入包含多組數據。每組數據第一行為 3 個整數 N, S 和 E (2 ≤ N ≤ 500, 1 ≤ S, E ≤ 100),即貓貓快線中的車站總數,起點和終點(即喵星機場所在站)編號。
下一行包含一個整數 M (1 ≤ M ≤ 1000),即經濟線的路段條數。
接下來有 M 行,每行 3 個整數 X, Y, Z (1 ≤ X, Y ≤ N, 1 ≤ Z ≤ 100),表示 TT 可以乘坐經濟線在車站 X 和車站 Y 之間往返,其中單程需要 Z 分鐘。
下一行為商業線的路段條數 K (1 ≤ K ≤ 1000)。
接下來 K 行是商業線路段的描述,格式同經濟線。
所有路段都是雙向的,但有可能必須使用商業車票才能到達機場。保證最優解唯一。
輸出:
對于每組數據,輸出3行。第一行按訪問順序給出 TT 經過的各個車站(包括起點和終點),第二行是 TT 換乘商業線的車站編號(如果沒有使用商業線車票,輸出"Ticket Not Used",不含引號),第三行是 TT 前往喵星機場花費的總時間。
本題不忽略多余的空格和制表符,且每一組答案間要輸出一個換行
樣例:
Input:
Output:
1 2 4 2 5思路:
將商務線與經濟線分開用鏈表存儲。
通過枚舉商務線,來確定最短路徑。設起點為s,終點為e,枚舉某條的商務線起點為x,終點為y,只需要找出min{dis1[u]+dis2[v]+w, dis1[v]+dis2[u]+w}即可,dis1數組存放了從起點s開始的到所有點的最短路徑值。dis2數組存放了從終點e開始的到所有點的最短路徑值。
需排除兩點不連通的情況。
代碼:
#include<iostream> #include<cstring> using namespace std; const int maxx=1000000; int n,m,k,s,e,tot,ans=maxx,head[maxx],dis1[maxx],dis2[maxx]; int pre1[maxx],pre2[maxx],p[maxx],sum,chu,a[maxx]; bool flag[maxx]; int ans_u,ans_v,ans_w; struct node {int v;int w;int next; }e1[maxx]; void add_edge(int u,int v,int w) {e1[++tot].v=v;e1[tot].w=w;e1[tot].next=head[u];head[u]=tot; } void dij1(int u) {memset(flag,0,sizeof(flag));for(int i=1;i<=n;i++)dis1[i]=maxx;dis1[u]=0;for(int i=1;i<=n;i++){int k=0,minn=maxx;for(int j=1;j<=n;j++)if(!flag[j]&&dis1[j]<minn){minn=dis1[j];k=j;}flag[k]=1;for(int j=head[k];j;j=e1[j].next)if(!flag[e1[j].v]&&dis1[e1[j].v]>dis1[k]+e1[j].w){dis1[e1[j].v]=dis1[k]+e1[j].w;pre1[e1[j].v]=k;}} } void dij2(int u) {memset(flag,0,sizeof(flag));for(int i=1;i<=n;i++)dis2[i]=maxx;dis2[u]=0;for(int i=1;i<=n;i++){int k=0,minn=maxx;for(int j=1;j<=n;j++)if(!flag[j]&&dis2[j]<minn){minn=dis2[j];k=j;}flag[k]=1;for(int j=head[k];j;j=e1[j].next)if(!flag[e1[j].v]&&dis2[e1[j].v]>dis2[k]+e1[j].w){dis2[e1[j].v]=dis2[k]+e1[j].w;pre2[e1[j].v]=k;}} } int main() {int x,y,z,u,v,w,T;while(scanf("%d%d%d",&n,&s,&e)!=EOF){if(T!=0) printf("\n");T++;memset(flag,0,sizeof(flag));memset(pre1,0,sizeof(pre1));memset(pre2,0,sizeof(pre2));memset(head,0,sizeof(head));memset(a,0,sizeof(a));tot=0;cin>>m;ans_u=0;sum=0;for(int i=1;i<=m;i++){cin>>x>>y>>z;add_edge(x,y,z);add_edge(y,x,z);}dij1(s);dij2(e);cin>>k;int ans=dis1[e];for(int i=1;i<=k;i++){cin>>u>>v>>w;if(dis1[u]+dis2[v]+w<ans){ans=dis1[u]+dis2[v]+w;ans_u=u;ans_v=v;}if(dis2[u]+dis1[v]+w<ans)//反向更新 {ans=dis2[u]+dis1[v]+w;ans_u=v;ans_v=u;}}int tmp;if(ans_u==0)//不需要商務線 {tmp=e;while(tmp){a[++sum]=tmp;if(tmp==s) break;tmp=pre1[tmp];}for(int i=sum;i>=2;i--) cout<<a[i]<<" ";cout<<a[1]<<endl;cout<<"Ticket Not Used"<<endl<<ans<<endl;}else//需要商務線 {tmp=ans_v;while(tmp){a[++sum]=tmp;if(tmp==e) break;tmp=pre2[tmp];}for(int i=1;i<=sum/2;i++)swap(a[i],a[sum-i+1]);tmp=ans_u;while(tmp){a[++sum]=tmp;if(tmp==s) break;tmp=pre1[tmp];}for(int i=sum;i>=2;i--) cout<<a[i]<<" ";cout<<a[1]<<endl;cout<<ans_u<<endl<<ans<<endl;}}return 0; }總結
以上是生活随笔為你收集整理的TT 的旅行日记 Week7作业B题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 美联储加息负面效应外溢
- 下一篇: jmeter+ant+jenkins接口