列表

详情


NC20131. [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)

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

输出描述

只有一行,包含一个整数,为最少花费。

示例1

输入:

5 6 1
0 4
0 1 5
1 2 5
2 3 5
3 4 5
2 3 3
0 2 100

输出:

8

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 175ms, 内存消耗: 56524K, 提交时间: 2020-06-01 10:00:59

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=4000010;
int n,m,k,s,t,dist[N];
int h[N],e[N],ne[N],w[N],idx;
void add(int a,int b,int c)
{
	e[idx]=b;
	w[idx]=c;
	ne[idx]=h[a];
	h[a]=idx++;
}
bool st[N];
void dij()
{
	priority_queue<pii,vector<pii>,greater<pii> > q;
	q.push({0,s});
	dist[s]=0;
	while(q.size())
	{
		int u=q.top().second;
		q.pop();
		if(st[u]) continue;
		st[u]=1;
		for(int i=h[u];i!=-1;i=ne[i])
		{
			int v=e[i];
			if(!st[v]&&dist[v]>dist[u]+w[i])
			{
				dist[v]=dist[u]+w[i];
				q.push({dist[v],v});
			}
		}
	}
}
int main()
{
	memset(h,-1,sizeof h);
	memset(dist,0x3f,sizeof dist);
	scanf("%d%d%d%d%d",&n,&m,&k,&s,&t);
	for(int i=1;i<=m;i++)
	{
		int a,b,c;
		scanf("%d%d%d",&a,&b,&c);
		for(int j=0;j<=k;j++)
		{
			add(a+j*n,b+j*n,c);
			add(b+j*n,a+j*n,c);
			if(j!=k)
			{
				add(a+j*n,b+(j+1)*n,0);
				add(b+j*n,a+(j+1)*n,0);
			}
		}
	}
	dij();
	int ans=0x3f3f3f3f;
	for(int i=0;i<=k;i++)
		ans=min(dist[t+i*n],ans);
	cout<<ans;
	return 0;
}

C++(g++ 7.5.0) 解法, 执行用时: 162ms, 内存消耗: 36888K, 提交时间: 2022-09-05 14:00:20

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5,M=6e6+6;
struct edge{
	int to,nx;
	ll v;
}e[M*2];
int hd[N],tot;
void add(int x,int y,int z){
	e[++tot]={y,hd[x],z};hd[x]=tot;
}
ll dis[N];
bool vis[N];
priority_queue<pair<ll,int>>q;
void dij(int s){
	memset(dis,0x3f,sizeof dis);
	q.push({0,s});
	dis[s]=0;
	while(q.size()){
		int x=q.top().second;q.pop();
		if(vis[x])continue;
		vis[x]=1;
		for(int i=hd[x];i;i=e[i].nx){
			int y=e[i].to;
			if(dis[x]+e[i].v<dis[y]){
				dis[y]=dis[x]+e[i].v;
				q.push({-dis[y],y});
			}
		}
	}
}
int n,m,k,s,t;
int main(){
	scanf("%d%d%d",&n,&m,&k);
	scanf("%d%d",&s,&t);
	for(int i=1;i<=m;++i){
		int x,y,z;scanf("%d%d%d",&x,&y,&z);
		for(int j=0;j<=k;++j){
			add(j*n+x,j*n+y,z);
			add(j*n+y,j*n+x,z);
		}
		for(int j=0;j<k;++j){
			add(j*n+x,(j+1)*n+y,0);
			add(j*n+y,(j+1)*n+x,0);
		}
	}
	for(int i=0;i<n;++i){
		for(int j=0;j<k;++j){
			add(j*n+i,(j+1)*n+i,0);
		}
	}
	dij(s);
	ll ans=dis[k*n+t];
	printf("%lld\n",ans);
}

C++(clang++ 11.0.1) 解法, 执行用时: 340ms, 内存消耗: 55972K, 提交时间: 2023-07-31 20:30:06

#include<bits/stdc++.h>
#define N 200005
#define int long long
using namespace std;
int n,m,k,dis[N],s,t,res=1e18;
typedef pair<int,int> PII;
bool vis[N];
struct node{
	int v,w;
};
vector<node> g[N];
void dijkstra(){
	memset(dis,0x3f,sizeof(dis));
	dis[s]=0;
	priority_queue<PII,vector<PII>,greater<PII>> pq;
	pq.push({0,s});
	while(pq.size()){
		auto K=pq.top();
		int t=K.second;
        pq.pop();
		if(vis[t]) continue;
		vis[t]=1;
		for(auto [j,w]:g[t]){
			if(dis[j]>dis[t]+w){
				dis[j]=dis[t]+w;
				pq.push({dis[j],j});
			}
		}
	}
}
signed main(){
	cin>>n>>m>>k>>s>>t;
    s++,t++;
	for(int i=1;i<=m;i++){
		int x,y,z;
		cin>>x>>y>>z;
		x++,y++;
		g[x].push_back({y,z});
		g[y].push_back({x,z});
		for(int j=1;j<=k;j++){
			g[j*n+x].push_back({j*n+y,z});
			g[j*n+y].push_back({j*n+x,z});
			g[(j-1)*n+x].push_back({j*n+y,0});
			g[(j-1)*n+y].push_back({j*n+x,0});
		}
	}
	dijkstra();
	for(int i=0;i<=k;i++) res=min(res,dis[i*n+t]);
	cout<<res;
}

上一题