ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

B-dijkstra-TT的旅行日记

2020-04-17 10:58:18  阅读:235  来源: 互联网

标签:int 商业 memset 日记 dijkstra maxn e1 TT


题意:

众所周知,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 前往喵星机场花费的总时间。

本题不忽略多余的空格和制表符,且每一组答案间要输出一个换行

输入样例

4 1 4
4
1 2 2
1 3 3
2 4 4
3 4 5
1
2 4 3

输出样例

1 2 4
25

My Solution:

本题商业线的引入使得问题变得复杂化,如果没有商业线,则问题变成了简单的图问题中的最短路问题。

我们发现加入商业线以后有两种做法,最短路中包含一条商业线或者不包含商业线。

对于不包含商业线的情况,我们可以求一个最短路。

对于包含商业线的情况,因为只走一条商业线,我们可以枚举每一条商业线的情况,然后取最小。

接下来,对于走(一条)商业线的问题怎么求短路呢?

分别从起点和终点跑一次最短路,然后取两次的最小值

min (dis1[u]+dis2[v]+w , dis1[v]+dis2[u]+w ) 

最后合并以上 以上情况,取最小即可!



  1 #include<iostream>
  2 #include<string.h>
  3 #include<algorithm> 
  4 using namespace std;
  5 const int maxn=1000010;
  6 int n,m,k,s,e,tot,ans=10000000,sum;
  7 int head[maxn],dis1[maxn],dis2[maxn];
  8 int pre1[maxn],pre2[maxn];
  9 int p[maxn],a[maxn];
 10 bool flag[maxn];
 11 int ans_u,ans_v,ans_w;
 12 struct node
 13 {
 14     int v;
 15     int w;
 16     int next;
 17 }e1[maxn];
 18 void add_edge(int u,int v,int w)
 19 {
 20     e1[++tot].v=v;
 21     e1[tot].w=w;
 22     e1[tot].next=head[u];
 23     head[u]=tot;
 24 }
 25 
 26 void dijkstra(int u,int *dis,int *pre)
 27 {
 28     memset(flag,0,sizeof(flag));
 29     for(int i=1;i<=n;i++)
 30     dis[i]=maxn;
 31     dis[u]=0;
 32     for(int i=1;i<=n;i++)
 33     {
 34         int k=0,minn=maxn;
 35         for(int j=1;j<=n;j++)
 36         if(!flag[j]&&dis[j]<minn)
 37         {
 38             minn=dis[j];
 39             k=j;
 40         }
 41         flag[k]=1;
 42         for(int j=head[k];j;j=e1[j].next)
 43         if(!flag[e1[j].v]&&dis[e1[j].v]>dis[k]+e1[j].w) //松弛 
 44         {
 45             dis[e1[j].v]=dis[k]+e1[j].w;
 46             pre[e1[j].v]=k;
 47         }
 48     }
 49 }
 50 int main()
 51 {
 52     int x,y,z,u,v,w;
 53     cin>>n>>s>>e; 
 54     while(1)
 55     {
 56         memset(flag,0,sizeof(flag));
 57         memset(pre1,0,sizeof(pre1));
 58         memset(pre2,0,sizeof(pre2));
 59         memset(head,0,sizeof(head));
 60         memset(a,0,sizeof(a));
 61         tot=0;
 62         cin>>m;
 63         ans_u=0;sum=0;
 64         for(int i=1;i<=m;i++)
 65         {
 66             cin>>x>>y>>z;
 67             add_edge(x,y,z);
 68             add_edge(y,x,z);
 69         }
 70         
 71         dijkstra(s,dis1,pre1) ;
 72         dijkstra(e,dis2,pre2) ;
 73         
 74         cin>>k;
 75         int ans=dis1[e];
 76         for(int i=1;i<=k;i++)
 77         {
 78             cin>>u>>v>>w;
 79             if(dis1[u]+dis2[v]+w<ans)
 80             {
 81                 ans=dis1[u]+dis2[v]+w;
 82                 ans_u=u;
 83                 ans_v=v;
 84             }
 85             if(dis2[u]+dis1[v]+w<ans)//再次更新 
 86             {
 87                 ans=dis2[u]+dis1[v]+w;
 88                 ans_u=v;
 89                 ans_v=u;
 90             }
 91         }
 92         int tmp;
 93         if(ans_u==0)//不需要商务线 
 94         {
 95             tmp=e;
 96             while(tmp)
 97             {
 98                 a[++sum]=tmp;
 99                 if(tmp==s) break;
100                 tmp=pre1[tmp];
101             }
102             for(int i=sum;i>=2;i--) cout<<a[i]<<" ";
103             cout<<a[1]<<endl;
104             cout<<"Ticket Not Used"<<endl<<ans<<endl;
105         }
106         else//需要商务线 
107         {
108             tmp=ans_v;
109             while(tmp)
110             {
111                 a[++sum]=tmp;
112                 if(tmp==e) break;
113                 tmp=pre2[tmp];
114             }
115             for(int i=1;i<=sum/2;i++)
116             swap(a[i],a[sum-i+1]);
117             tmp=ans_u;
118             while(tmp)
119             {
120                 a[++sum]=tmp;
121                 if(tmp==s) break;
122                 tmp=pre1[tmp];
123             }
124             for(int i=sum;i>=2;i--) cout<<a[i]<<" ";
125             cout<<a[1]<<endl;
126             cout<<ans_u<<endl<<ans<<endl;
127         }
128         
129         if(cin>>n>>s>>e)
130             cout<<endl;     //每个输出换行 
131         else 
132             break;
133     }
134     return 0;
135 }

 



 

标签:int,商业,memset,日记,dijkstra,maxn,e1,TT
来源: https://www.cnblogs.com/liuzhuan-xingyun/p/12717899.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有