飞行路线 HYSBZ - 2763 (分层图+Dijkstra && Spfa)

飞行路线

  Alice和Bob现在要乘飞机旅行,他们选择了一家相对便宜的航空公司。该航空公司一共在n个城市设有业务,设这些城市分别标记为0到n-1,一共有m种航线,每种航线连接两个城市,并且航线有一定的价格。Alice和Bob现在要从一个城市沿着航线到达另一个城市,途中可以进行转机。航空公司对他们这次旅行也推出优惠,他们可以免费在最多k种航线上搭乘飞机。那么Alice和Bob这次出行最少花费多少?

Input

数据的第一行有三个整数,n,m,k,分别表示城市数,航线数和免费乘坐次数。

第二行有两个整数,s,t,分别表示他们出行的起点城市编号和终点城市编号。(0<=s,t<n)

接下来有m行,每行三个整数,a,b,c,表示存在一种航线,能从城市a到达城市b,或从城市b到达城市a,价格为c。(0<=a,b<n,a与b不相等,0<=c<=1000)

Output

只有一行,包含一个整数,为最少花费。

Sample Input

5 6 1

0 4

0 1 5

1 2 5

2 3 5

3 4 5

2 3 3

0 2 100

Sample Output

8

Hint

对于30%的数据,2<=n<=50,1<=m<=300,k=0;

对于50%的数据,2<=n<=600,1<=m<=6000,0<=k<=1;

对于100%的数据,2<=n<=10000,1<=m<=50000,0<=k<=10.

题解:

对于k次免费花费,我们可以把图想像为有k+1层,从第0层到第k层,第0层表示没有用过这k次机会,第i层表示用过i次免费花费。对于分层,有两种方法。本题为双向边。

注意:最后要从所有层中的终点找答案,因为如果s-t只有少于k条路,而你选取免费k次在到达终点的答案就可能不对。

1.建图时分层:建k+1层图。然后有边的两个点,多建一条到下一层边权为0的单向边,如果走了这条边就表示用了一次免费机会

比如共有N个点,1~n表示第一层,(1+n)~(n+n)代表第二层,(1+2*n)~(n+2*n)代表第三层,(1+i*n)~(n+i*n)代表第i层。

注意该种方法:因为要建K+1层图,数组要开到n*(k+1),点的个数也为n*(k+1)。

Dijkstra解法:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <queue>
 5 #include <algorithm>
 6 #define inf 0x3f3f3f3f
 7 using namespace std;
 8 int cnt,n,m,k;
 9 const int maxn=1e6+10;
10 const int maxm=1e7;
11 int head[maxn],dis[maxn],vis[maxn];
12 struct edge{
13     int to;
14     int next;
15     int w;
16 }e[maxm];
17 void init()
18 {
19     memset(vis,0,sizeof(vis));
20     memset(head,-1,sizeof(head));
21     memset(dis,inf,sizeof(dis));
22     cnt=0;
23 }
24 void add(int x,int y,int w)
25 {
26     e[cnt].to=y;
27     e[cnt].w=w;
28     e[cnt].next=head[x];
29     head[x]=cnt++;
30 }
31 struct node{
32     int pos;
33     int cost;
34     node(){}
35     node(int pos,int cost):pos(pos),cost(cost){}
36     friend bool operator < (node a,node b)
37     {
38         return a.cost>b.cost;
39     }
40 };
41 void dijkstra(int st)
42 {
43   priority_queue<node>q;
44   dis[st]=0;
45   q.push(node(st,0));
46   while(!q.empty())
47   {
48       node now=q.top();
49       q.pop();
50       if(vis[now.pos])
51             continue;
52       vis[now.pos]=1;
53       for(int i=head[now.pos];i!=-1;i=e[i].next)
54       {
55           int u=e[i].to;
56           if(dis[u]>dis[now.pos]+e[i].w)
57           {
58               dis[u]=dis[now.pos]+e[i].w;
59               q.push(node(u,dis[u]));
60           }
61       }
62   }
63 }
64 int main()
65 {
66     cin>>n>>m>>k;
67     int st,ed;
68     cin>>st>>ed;
69     int a,b,c;
70     init();
71     for(int i=0;i<m;i++)
72     {
73         scanf("%d%d%d",&a,&b,&c);
74         for(int j=0;j<=k;j++)
75         {
76             add(a+j*n,b+j*n,c);
77             add(b+j*n,a+j*n,c);
78             if(j!=k)
79             {
80                 add(a+j*n,b+(j+1)*n,0);
81                 add(b+j*n,a+(j+1)*n,0);
82             }
83         }
84     }
85     dijkstra(st);
86     int ans=214748364;
87     for(int i=0;i<=k;i++)
88     {
89         ans=min(ans,dis[i*n+ed]);
90     }
91     printf("%d\n",ans);
92     return 0;
93 }

spfa解法:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <queue>
 5 #include <algorithm>
 6 #define inf 0x3f3f3f3f
 7 using namespace std;
 8 int cnt,n,m,k;
 9 const int maxn=3e6+10;
10 const int maxm=1e7;
11 int head[maxn],dis[maxn],vis[maxn];
12 struct edge{
13     int to;
14     int next;
15     int w;
16 }e[maxn<<1];
17 void init()
18 {
19     memset(vis,0,sizeof(vis));
20     memset(head,-1,sizeof(head));
21     memset(dis,inf,sizeof(dis));
22     cnt=0;
23 }
24 void add(int x,int y,int w)
25 {
26     e[cnt].to=y;
27     e[cnt].w=w;
28     e[cnt].next=head[x];
29     head[x]=cnt++;
30 }
31 struct node{
32     int pos;
33     int cost;
34     node(){}
35     node(int pos,int cost):pos(pos),cost(cost){}
36     friend bool operator < (node a,node b)
37     {
38         return a.cost>b.cost;
39     }
40 };
41 void dijkstra(int st)
42 {
43   priority_queue<node>q;
44   dis[st]=0;
45   q.push(node(st,0));
46   vis[st]=1;
47   while(!q.empty())
48   {
49       node now=q.top();
50       q.pop();
51       vis[now.pos]=0;
52       for(int i=head[now.pos];i!=-1;i=e[i].next)
53       {
54           int u=e[i].to;
55           if(dis[u]>dis[now.pos]+e[i].w)
56           {
57               dis[u]=dis[now.pos]+e[i].w;
58               if(!vis[u])
59                     vis[u]=1;
60               q.push(node(u,dis[u]));
61           }
62       }
63   }
64 }
65 int main()
66 {
67     int st,ed;
68     scanf("%d%d%d",&n,&m,&k);
69     scanf("%d%d",&st,&ed);
70     int a,b,c;
71     init();
72     for(int i=0;i<m;i++)
73     {
74         scanf("%d%d%d",&a,&b,&c);
75         for(int j=0;j<=k;j++)
76         {
77             add(a+j*n,b+j*n,c);
78             add(b+j*n,a+j*n,c);
79             if(j!=k)
80             {
81                 add(a+j*n,b+(j+1)*n,0);
82                 add(b+j*n,a+(j+1)*n,0);
83             }
84         }
85     }
86     dijkstra(st);
87     int ans=214748364;
88     for(int i=0;i<=k;i++)
89     {
90         ans=min(ans,dis[i*n+ed]);
91     }
92     printf("%d\n",ans);
93     return 0;
94 }

原文地址:https://www.cnblogs.com/1013star/p/9576487.html

时间: 2024-10-03 05:05:01

飞行路线 HYSBZ - 2763 (分层图+Dijkstra && Spfa)的相关文章

【BZOJ-3627】路径规划 分层图 + Dijkstra + spfa

3627: [JLOI2014]路径规划 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 186  Solved: 70[Submit][Status][Discuss] Description 相信大家都用过地图上的路径规划功能,只要输入起点终点就能找出一条最优路线.现在告诉你一张地图的信息,请你找出最优路径(即最短路径).考虑到实际情况,一辆车加满油能开的时间有限,所以在地图上增加了几个加油站. 地图由点和双向边构成,每个点代表一个路口,也有可

Bzoj 2763: [JLOI2011]飞行路线 拆点,分层图,最短路,SPFA

2763: [JLOI2011]飞行路线 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1694  Solved: 635[Submit][Status][Discuss] Description Alice和Bob现在要乘飞机旅行,他们选择了一家相对便宜的航空公司.该航空公司一共在n个城市设有业务,设这些城市分别标记为0到n-1,一共有m种航线,每种航线连接两个城市,并且航线有一定的价格.Alice和Bob现在要从一个城市沿着航线到达另一个城市

BZOJ 2763 分层图最短路

突然发现我不会分层图最短路,写一发. 就是同层中用双向边相连,用单向边连下一层 1 #include <cstdio> 2 #include <algorithm> 3 #include <iostream> 4 #include <string> 5 #include <cstring> 6 #include <queue> 7 #include <vector> 8 #define pa pair<int,int

BZOJ-3627路径规划分层图+Dijkstra+spfa2au

廈扇晾拷諏酝盖接叫淳布棺凡沽岸 洪灵枢只能硬着头皮与陆诩并肩而行逐渐与其他人拉开距离洪灵枢随后发现两人身后远 罾侗漭孀 陆丞燕翘了翘嘴角徐凤年笑着转身再转身果然看到她双指拧袖站在门口没有挪步朝 身份显赫的世子殿下.慕容桐皇还能坚持始终与徐凤年对视. 轧检ホ¢ 匦函挽 一名白袍男子从船舱中走出跟两人擦肩而过走到两鬓斑白的儒生附近低头瞥了一眼. 上回在龙晴郡鱼龙帮也露过面这次被调入陵州将军府徐凤年记得当时跟汪植要人的时候 亲卫没有转身只是突然嘶吼道:"不带!老子就带两分银子一壶的破酒给你们到时候将

bzoj 1579: [Usaco2009 Feb]Revamping Trails 道路升级——分层图+dijkstra

Description 每天,农夫John需要经过一些道路去检查牛棚N里面的牛. 农场上有M(1<=M<=50,000)条双向泥土道路,编号为1..M. 道路i连接牛棚P1_i和P2_i (1 <= P1_i <= N; 1 <= P2_i<= N). John需要T_i (1 <= T_i <= 1,000,000)时间单位用道路i从P1_i走到P2_i或者从P2_i 走到P1_i 他想更新一些路经来减少每天花在路上的时间.具体地说,他想更新K (1 &l

bzoj 2763 [JLOI2011]飞行路线——分层图

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2763 分层图两种方法的练习. 1.把图分成k+1层,本层去上面一层的边免费.但空间时间都不算优秀. #include<iostream> #include<cstdio> #include<cstring> #include<queue> #define ll long long using namespace std; const int N=1e4

bzoj 2763: [JLOI2011]飞行路线【分层图+spfa】

为什么早年的题总是从0开始标号啊--又zz了一次WA 分层图的题只有这一个套路吧,建分层图,然后优化时间是分层跑spfa然后层与层之间单独跑即可 #include<iostream> #include<cstdio> #include<queue> #include<cstring> using namespace std; const int N=50005,inf=1e9; int n,m,k,s,t,h[N],cnt,dis[N],d[N]; bool

bzoj2763: [JLOI2011]飞行路线(分层图spfa)

2763: [JLOI2011]飞行路线 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3234  Solved: 1235[Submit][Status][Discuss] Description Alice和Bob现在要乘飞机旅行,他们选择了一家相对便宜的航空公司.该航空公司一共在n个城市设有业务,设这些城市分别标记为0到n-1,一共有m种航线,每种航线连接两个城市,并且航线有一定的价格.Alice和Bob现在要从一个城市沿着航线到达另一个城

BZOJ 2763 JLOI 2011 飞行路线 分层图+最短路

题目大意:两个小屁孩要乘飞机去旅行.现在给一些无向边和边权,另外他们还有K次免费乘坐飞机的机会,问从起点到终点的最小话费是什么. 思路:分层图第一题.之前听到分层图还以为是真的建K个图,然后不同层数之间的点连边跑最短路..后来经同学讲解才发现我想多了.. 其实还是动归的思想(最短路不也是动归的思想么(`?ω?′)),f[ i ][ j ]表示在j位置时,已经用了i次免费机会的时候的最小花费,然后在SPFA里多一维的转移就可以了. PS:BZOJ上这个题还是挺卡常数的,我之前用queue用了938