P4568 [JLOI2011]飞行路线 (分层图最短路 dp思想)

k次免费机会最短路。
两种思路:1.dp;dis[to][free]代表从出发点到to点用了free次免费机会的最短路,然后dijkstra跑。
2.建分层图;在建边时比如a,b,c,建边时就建(a0+a,b0+b,c)(b0+b,a0+a,c)(a1+a,b1+b,0)…(ak+a,bk+b,0)(bk+b,ak+a,c),然后跑dijkstra。比起第一种方法占内存,因为边的数量是m*(k+1)。

#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#include<queue>
using namespace std;
struct skt{
	int now,free,w;
	friend bool operator<(skt a,skt b){
		return a.w>b.w;
	}
};
int n,kk;
int dis[10100][15];
bool have[10100][15];
vector<int>v[10100],w[10100];
void dijkstra(int now){
	int i;
	memset(dis,0x3f,sizeof(dis));
	memset(have,false,sizeof(have));
	priority_queue<skt>q;
	skt s;
	s.now=now;
	s.free=0;
	s.w=0;
	dis[now][0]=0;
	q.push(s);
	while(!q.empty()){
		skt t;
		t=q.top();
		q.pop();
		int from=t.now;
		int free=t.free;
		if(have[from][free])
		continue;
		have[from][free]=true;
		for(i=0;i<v[from].size();i++){
			int to=v[from][i];
			int cost=w[from][i];
			if(dis[to][free]>cost+dis[from][free]){
				dis[to][free]=cost+dis[from][free];
				skt k;
				k.now=to;k.free=free;k.w=dis[to][free];
				q.push(k);
			}
			if(free<kk){
				if(dis[to][free+1]>dis[from][free]){
					dis[to][free+1]=dis[from][free];
					skt k;
					k.now=to;k.free=free+1;k.w=dis[to][free+1];
					q.push(k);
				}
			}
		}
	}
}
int main(void){
	int m,i,a,b,c,s,t;
	scanf("%d%d%d",&n,&m,&kk);
	scanf("%d%d",&s,&t);
	for(i=0;i<m;i++){
		scanf("%d%d%d",&a,&b,&c);
		v[a].push_back(b);
		w[a].push_back(c);
		v[b].push_back(a);
		w[b].push_back(c);
	}
	dijkstra(s);
	int ans=dis[t][0];
	for(i=0;i<=kk;i++){
		ans=min(ans,dis[t][i]);
	}
	cout<<ans<<"\n";
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值