bzoj2763: [JLOI2011]飞行路线
题目描述
Alice和Bob现在要乘飞机旅行,他们选择了一家相对便宜的航空公司。该航空公司一共在n个城市设有业务,设这些城市分别标记为0到n-1,一共有m种航线,每种航线连接两个城市,并且航线有一定的价格。Alice和Bob现在要从一个城市沿着航线到达另一个城市,途中可以进行转机。航空公司对他们这次旅行也推出优惠,他们可以免费在最多k种航线上搭乘飞机。那么Alice和Bob这次出行最少花费多少?
输入
数据的第一行有三个整数,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)
输出
只有一行,包含一个整数,为最少花费。
样例输入
5 6 1
0 4
0 1 5
1 2 5
2 3 5
3 4 5
2 3 3
0 2 100
0 4
0 1 5
1 2 5
2 3 5
3 4 5
2 3 3
0 2 100
样例输出
8
题解
分层图最短路,拆点然后将乘坐免费航线的个数分层,跑spfa就行了。
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<queue> 5 #define maxn 10005 6 #define inf 1<<29 7 int head[maxn],vis[maxn][11],d[maxn][11]; 8 int ecnt,n,m,lim,s,t,ans=inf; 9 using namespace std; 10 struct edge{ 11 int u,v,w,next; 12 }E[maxn*10]; 13 struct node{ 14 int u,num; 15 node(int x,int y):u(x),num(y){} 16 }; 17 void addedge(int u,int v,int w) 18 { 19 E[++ecnt].u=u; 20 E[ecnt].v=v; 21 E[ecnt].w=w; 22 E[ecnt].next=head[u]; 23 head[u]=ecnt; 24 } 25 void spfa(int x) 26 { 27 queue<node> q; 28 memset(d,127/3,sizeof(d)); 29 d[x][0]=0; 30 node now(x,0); 31 node next(0,0); 32 q.push(now); 33 vis[x][0]=1; 34 while(!q.empty()) 35 { 36 node now=q.front();q.pop(); 37 int dd=now.u; 38 int k=now.num; 39 vis[dd][k]=0; 40 for(int i=head[dd] ; i ; i=E[i].next ) 41 { 42 int v=E[i].v; 43 int w=E[i].w; 44 if(d[dd][k]+w<d[v][k]) 45 { 46 d[v][k]=d[dd][k]+w; 47 if(!vis[v][k]) 48 { 49 vis[v][k]=1; 50 next.u=v; 51 next.num=k; 52 q.push(next); 53 } 54 } 55 if(d[dd][k]<d[v][k+1]&&k<lim) 56 { 57 d[v][k+1]=d[dd][k]; 58 if(!vis[v][k+1]) 59 { 60 vis[v][k+1]=1; 61 next.u=v; 62 next.num=k+1; 63 q.push(next); 64 } 65 } 66 } 67 } 68 for(int i=0 ; i<=lim ; ++i) 69 ans=min(ans,d[t][i]); 70 printf("%d",ans); 71 } 72 int main() 73 { 74 int u,v,w; 75 scanf("%d%d%d%d%d",&n,&m,&lim,&s,&t); 76 for(int i=1 ; i<=m ; ++i ) 77 { 78 scanf("%d%d%d",&u,&v,&w); 79 addedge(u,v,w); 80 addedge(v,u,w); 81 } 82 spfa(s); 83 return 0; 84 }