【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

样例输出

8


题解

分层图Spfa

dis[i][j]表示免费j条后i到s的最短路。

然后跑分层图Spfa。

第一次写分层图,也是第一次用pair,所以代码略丑,凑合着看吧。

#include <cstdio>
#include <cstring>
#include <queue>
#include <utility>
using namespace std;
queue<pair<int , int> > q;
int head[10010] , to[100010] , len[100010] , next[100010] , cnt , dis[10010][11] , inq[10010][11];
void add(int x , int y , int z)
{
	to[++cnt] = y;
	len[cnt] = z;
	next[cnt] = head[x];
	head[x] = cnt;
}
int main()
{
	int n , m , k , i , s , t , x , y , z , ans = 0x3f3f3f3f;
	pair<int , int> u;
	scanf("%d%d%d%d%d" , &n , &m , &k , &s , &t);
	for(i = 1 ; i <= m ; i ++ )
		scanf("%d%d%d" , &x , &y , &z) , add(x , y , z) , add(y , x , z);
	memset(dis , 0x3f , sizeof(dis));
	dis[s][0] = 0;
	q.push(make_pair(s , 0));
	while(!q.empty())
	{
		u = q.front();
		q.pop();
		x = u.first , y = u.second;
		inq[x][y] = 0;
		for(i = head[x] ; i ; i = next[i])
		{
			if(dis[to[i]][y] > dis[x][y] + len[i])
			{
				dis[to[i]][y] = dis[x][y] + len[i];
				if(!inq[to[i]][y]) inq[to[i]][y] = 1 , q.push(make_pair(to[i] , y));
			}
			if(y < k && dis[to[i]][y + 1] > dis[x][y])
			{
				dis[to[i]][y + 1] = dis[x][y];
				if(!inq[to[i]][y + 1]) inq[to[i]][y + 1] = 1 , q.push(make_pair(to[i] , y + 1));
			}
		}
	}
	for(i = 0 ; i <= k ; i ++ ) ans = min(ans , dis[t][i]);
	printf("%d\n" , ans);
	return 0;
}

 

posted @ 2017-02-28 19:44  GXZlegend  阅读(453)  评论(0编辑  收藏  举报