模板题:https://www.luogu.com.cn/problem/P4568
题目描述
Alice 和 Bob 现在要乘飞机旅行,他们选择了一家相对便宜的航空公司。该航空公司一共在nn个城市设有业务,设这些城市分别标记为 00到 n-1,一共有 m 种航线,每种航线连接两个城市,并且航线有一定的价格。
Alice 和 Bob 现在要从一个城市沿着航线到达另一个城市,途中可以进行转机。航空公司对他们这次旅行也推出优惠,他们可以免费在最多 kk 种航线上搭乘飞机。那么 Alice 和 Bob 这次出行最少花费多少?
输入格式
第一行三个整数 n,m,k,分别表示城市数,航线数和免费乘坐次数。
接下来一行两个整数 s,t分别表示他们出行的起点城市编号和终点城市编号。
接下来 mm行,每行三个整数a,b,c表示存在一种航线,能从城市 aa到达城市 b,或从城市 b 到达城市 a,价格为 c。
输出格式
输出一行一个整数,为最少花费。
题解:对于n个结点的图看成是一层,这里可以省略k次航线路费。那么就可以i看作是k+1层的图,每一层都是n个结点,第0层表示较少了0次花费,第i层表示减少了i次花费。所以disi,j=min{min{disfrom,j−1},min{disfrom,j+w}}
AC代码:
#include<bits/stdc++.h> using namespace std; const int N=1e4+10; const int M=5e4+10; struct st{ int from,to,next,dis; }edge[M*2]; int n,m,k,head[N],cnt; int dis[N][11]; struct node{ int u,j,dis; node(int a=0,int b=0,int c=0):u(a),j(b),dis(c){} bool operator>(const struct node a1)const { return dis>a1.dis; } }; void addedge(int u,int v,int w){ cnt++; edge[cnt].from=u; edge[cnt].to=v; edge[cnt].dis=w; edge[cnt].next=head[u]; head[u]=cnt; } void dijkstra(int s){ memset(dis,0x3f,sizeof(dis)); int vis[N][11]; memset(vis,0,sizeof(vis)); priority_queue<struct node ,vector<struct node>,greater<struct node> >q; struct node a1; q.push(node(s,0,0)); while(!q.empty()){ a1=q.top();q.pop(); if(vis[a1.u][a1.j]==1) continue; vis[a1.u][a1.j]=1; dis[a1.u][a1.j]=a1.dis; for(int i=head[a1.u];i;i=edge[i].next){ if(vis[edge[i].to][a1.j]==1) ; else { q.push(node(edge[i].to,a1.j,a1.dis+edge[i].dis)); } if(vis[edge[i].to][a1.j+1]==1||a1.j+1>k) ; else { q.push(node(edge[i].to,a1.j+1,a1.dis)); } } } } int main(){ cin>>n>>m>>k; int s,t; cin>>s>>t; for(int i=1,a,b,c;i<=m;i++){ cin>>a>>b>>c; addedge(a,b,c); addedge(b,a,c); } dijkstra(s); int ans=0x3f3f3f3f; for(int i=0;i<=k;i++){ ans=min(ans,dis[t][i]); } cout<<ans<<endl; return 0; }
写于2020/8/11 23:25