To_Heart—题解——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

样例输出

8

数据范围与提示

对于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.

题解

乍一看,哇塞,这不是分层图最短路的板子吗???

又一看,哇塞,不会打分层图

于是采取其它的方法;

仔细一看,可以DP呀!!!

对于定义dp[i][j],表示第i点到源点使用了j次免费机会的最短路径;

那么到达dp[i][j]的方式有两种

  1. 由i所连接的点直接到达i;
  2. 由i所连接的点使用一次免费后到达i;

所以dp[i][j]=min(dp[v][j-1],dp[v][j]+w)

其中,v为所有连接i的店,w为其边权;

代码

#include<bits/stdc++.h>
using namespace std;

struct zz{
    
    
	int u,w,k; 
};

bool operator <(zz a,zz b){
    
    
	return a.w>b.w;
}

vector<zz> v[10005];
int dp[10005][15];
bool f[10005][15];
int n,m,tot;

void Dijkstra(int st,int ed){
    
    
	memset(dp,0x3f,sizeof dp);
	dp[st][0]=0;
	priority_queue<zz> q;
	q.push(zz{
    
    st,0,0});
	while(q.size()){
    
    
		zz now;
		now=q.top();
		int nowk=now.k;
		int nowans=now.w;
		int u=now.u;
		q.pop();
		if(f[u][nowk])
			continue;
		f[u][nowk]=1;
		for(int i=0;i<v[u].size();i++){
    
    
			int u1=v[u][i].u;
			int w=v[u][i].w;
			if(dp[u1][nowk]>dp[u][nowk]+w&&!f[u1][nowk]){
    
    
				dp[u1][nowk]=dp[u][nowk]+w;
				q.push(zz{
    
    u1,dp[u1][nowk],nowk});
			}
			if(nowk+1<=tot){
    
    
				if(dp[u1][nowk+1]>dp[u][nowk]&&!f[u1][nowk+1]){
    
    
					dp[u1][nowk+1]=dp[u][nowk];
					q.push(zz{
    
    u1,dp[u1][nowk+1],nowk+1});
				}
			} 
			
		}
	}
	int Min=0x3f3f3f3f;
	for(int i=0;i<=tot;i++){
    
    
		Min=min(Min,dp[ed][i]);
		//printf("%d %d %d\n",ed,i,dp[ed][i]);
	}
	printf("%d",Min);
}

int main(){
    
    
	int st,ed;
	scanf("%d%d%d",&n,&m,&tot);
	scanf("%d%d",&st,&ed);
	for(int i=1;i<=m;i++){
    
    
		int x,y,z;
		scanf("%d%d%d",&x,&y,&z);
		v[x].push_back(zz{
    
    y,z,0});
		v[y].push_back(zz{
    
    x,z,0});
	}
	Dijkstra(st,ed);
	return 0;
}

おすすめ

転載: blog.csdn.net/xf2056188203/article/details/108954089