您的位置:首页 > 其它

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):

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: