2017年8月10号提高组T2 飞行
2017-08-17 19:36
239 查看
Description
有n个城市,编号为0到n-1。小B想从城市s到城市t。他们选择了一家航空公司,这家公司有m种航线,每种航线连接了两个不同的城市。看在小B是个妹子的份上,航空公司的老总给了小B一点优惠:小B可以免费在最多k种航线上搭乘飞机。问小B最小花费是多少。
Input
第一行三个整数n,m,k,分别表示城市数量,航线数量和免费搭乘的航线数量。
第二行两个整数s,t,表示起点和终点。
接下来m行,每行三个整数a.b.c,表示一种航线,即可以从a到b,也可以从b到a,花费为c。
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,c<=1000.
做法:其实和普通最短路没啥区别,在外围多枚举一个k就好了(用spfa或dij都可以)
代码如下(spfa):
有n个城市,编号为0到n-1。小B想从城市s到城市t。他们选择了一家航空公司,这家公司有m种航线,每种航线连接了两个不同的城市。看在小B是个妹子的份上,航空公司的老总给了小B一点优惠:小B可以免费在最多k种航线上搭乘飞机。问小B最小花费是多少。
Input
第一行三个整数n,m,k,分别表示城市数量,航线数量和免费搭乘的航线数量。
第二行两个整数s,t,表示起点和终点。
接下来m行,每行三个整数a.b.c,表示一种航线,即可以从a到b,也可以从b到a,花费为c。
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,c<=1000.
做法:其实和普通最短路没啥区别,在外围多枚举一个k就好了(用spfa或dij都可以)
代码如下(spfa):
#include <cstdio> #include <cstring> #include <iostream> using namespace std; struct arr { int to,next,w; }f[100007]; int ls[50007],list[100007],n,m,k,s,t,e,d[50007][11]; bool v[50007]; void spfa() { for (int i=0;i<n;i++) for (int j=0;j<=k;j++) d[i][j]=123456789; for (int i=0;i<=k;i++) d[s][i]=0; list[1]=s; v[s]=1; int head=0,tail=1; while (head<tail) { head++; for (int i=ls[list[head]];i;i=f[i].next) { bool b=false; if (d[list[head]][0]+f[i].w<d[f[i].to][0]) { d[f[i].to][0]=d[list[head]][0]+f[i].w; if (!b && !v[f[i].to]) { v[f[i].to]=1; b=true; tail++; list[tail]=f[i].to; } } for (int j=1;j<=k;j++) { if (d[list[head]][j-1]<d[f[i].to][j]) { d[f[i].to][j]=d[list[head]][j-1]; if (!b && !v[f[i].to]) { v[f[i].to]=1; b=true; tail++; list[tail]=f[i].to; } } if (d[list[head]][j]+f[i].w<d[f[i].to][j]) { d[f[i].to][j]=d[list[head]][j]+f[i].w; if (!b && !v[f[i].to]) { v[f[i].to]=1; b=true; tail++; list[tail]=f[i].to; } } } } v[list[head]]=0; } } int main() { cin>>n>>m>>k; cin>>s>>t; int o,p,q; for (int i=1;i<=m;i++) { scanf("%d%d%d",&p,&q,&o); e++; f[e].to=q; f[e].next=ls[p]; ls[p]=e; f[e].w=o; e++; f[e].to=p; f[e].next=ls[q]; ls[q]=e; f[e].w=o; } spfa(); int ans=10000000; for (int i=0;i<=k;i++) ans=min(ans,d[t][i]); cout<<ans; }
相关文章推荐
- 2017年8月10号提高组T2 飞行
- 2017年8月10号提高组T2 飞行
- SSL2677 2017年8月10号提高组T2 飞行(spfa)
- 【SSLGZ 2677】2017年8月10号提高组T2 飞行
- JZOJsenior1396.2017.04.08【NOIP提高组】模拟赛B组 T2包裹快递
- Noip提高组 2014 Day1 T2 联合权值 模拟
- [DP] ZROI 2017提高1 T2.给 Ca
- SSL2795 2017年10月26日提高组T2 幸运值(组合)
- SSL2843 2017年11月8日提高组T2 拆网线(树形dp)
- XJOI NOIP16提高组赛前训练19-day1 T2:过路费(SPFA)
- Noip 提高组 2011 Day2 T2 聪明的质检员 二分法
- SSL2844 2017年11月8日提高组T2 奇怪的队列(线段树贪心)
- 选择客栈 NOIP2011 提高组 Day1 T2
- 2017年8月10号提高组T3 树
- 【前缀和】【前缀MAX】洛谷 P1351 NOIP2014提高组 day1 T2 联合权值
- [DP] ZROI 2017提高 5 T2. 石头剪刀布
- NOIP 2014 提高组 Day1 T2 联合权值
- 【SSLGZ 2780】2017年10月20日提高T2 收银员(01背包)
- 全国信息学奥林匹克联赛(NOIP2011)复赛 提高组 day2 T2 聪明的质监员
- 2017年8月8日提高组T2 呀!回文串