• 洛谷 P4568 [JLOI2011]飞行路线 题解


    P4568 [JLOI2011]飞行路线

    题目描述

    Alice和Bob现在要乘飞机旅行,他们选择了一家相对便宜的航空公司。该航空公司一共在(n)个城市设有业务,设这些城市分别标记为(0)(n-1),一共有(m)种航线,每种航线连接两个城市,并且航线有一定的价格。

    Alice和Bob现在要从一个城市沿着航线到达另一个城市,途中可以进行转机。航空公司对他们这次旅行也推出优惠,他们可以免费在最多(k)种航线上搭乘飞机。那么Alice和Bob这次出行最少花费多少?

    输入格式

    数据的第一行有三个整数,(n,m,k),分别表示城市数,航线数和免费乘坐次数。
    第二行有两个整数,(s,t),分别表示他们出行的起点城市编号和终点城市编号。
    接下来有m行,每行三个整数,(a,b,c),表示存在一种航线,能从城市(a)到达城市(b),或从城市(b)到达城市(a),价格为(c)

    输出格式

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

    输入输出样例

    输入 #1

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

    输出 #1

    8

    说明/提示

    对于30%的数据,(2 le n le 50,1 le m le 300,k=0;)
    对于50%的数据,(2 le n le 600,1 le m le 6000,0 le k le 1;)
    对于100%的数据,(2 le n le 10000,1 le m le 50000),(0 le k le 10,0 le s,t<n,0 le a,b<n,a eq b,0 le c le 1000)

    2018.12.10 增加一组 hack 数据

    【思路】

    分层图 + dijkstra
    分层图板子题
    如果想了解分层图请看这里
    了解分层图

    【题目大意】

    从1到n跑
    其中可以让k条路的耗时变为原来的一半
    求最小耗时

    【题目分析】

    如果你不是第一次做分层图的话
    那看到这k条路减半
    一定会想到一个很有意思的算法分层图
    分层图就是专门用来解决这种k条路减半的问题的
    不过需要开很大的空间
    开数组的时候要好好斟酌一下
    不然很容易出问题

    【核心思路】

    正常建一遍图
    然后赋值k遍
    第i张图作为用了i次免费的机会
    所以两张图之间是免费机会用的路
    那就需要赋值为0
    这样直接跑dijkstra就完全没有问题

    【完整代码】

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    struct point
    {
    	int w,x;
    	bool operator < (const point & xx)const
    	{
    		return xx.w < w;
    	}
    };
    const int Max = 4000000;
    struct node
    {
    	int y,ne,z;
    }a[Max];
    int sum = 0,head[Max];
    int d[Max];
    
    void add(int x,int y,int z)
    {
    	a[++ sum].y = y;
    	a[sum].ne = head[x];
    	a[sum].z = z;
    	head[x] = sum;
    }
    bool use[Max];
    int s,t;
    priority_queue<point>q;
    void dj()
    {
    	memset(d,0x3f,sizeof(d));
    	d[s] = 0;
    	q.push((point){0,s});
    	while(!q.empty())
    	{
    		point qwq = q.top();
    		q.pop();
    		int x = qwq.x,w = qwq.w;
    		if(use[x] == true)
    			continue;
    		else
    			use[x] = true;
    		for(register int i = head[x];i != 0;i = a[i].ne)
    		{
    			int awa = a[i].y;
    			if(d[awa] > d[x] + a[i].z)
    			{
    				d[awa] = d[x] + a[i].z;
    				if(use[awa] == false)
    					q.push((point){d[awa],awa});
    			}
    		}
    	}
    }
    int main()
    {
    	int n,m,k;
    	cin >> n >> m >> k;
    	cin >> s >> t;
    	int x,y,z;
    	for(register int i = 1;i <= m;++ i)
    	{
    		cin >> x >> y >> z;
    		add(x,y,z),add(y,x,z);
    		for(register int j = 1;j <= k;++ j)
    		{
    			add(j * n + x,j * n + y,z);
    			add(j * n + y,j * n + x,z);
    			add((j - 1) * n + x,j * n + y,0);
    			add((j - 1) * n + y,j * n + x,0);
    		}
    	}
    	dj();
    	int M = 0x7fffffff;
    	for(register int i = 0;i <= k;++ i)
    		M = min(M,d[i * n + t]);
    	cout << M << endl;
    	return 0;
    }
    
  • 相关阅读:
    P3350 [ZJOI2016]旅行者
    P4178 Tree
    P2375 [NOI2014]动物园
    P2827 蚯蚓
    1002: [FJOI2007]轮状病毒
    1070: [SCOI2007]修车
    AtCoder Grand Contest 021完整题解
    Running to the End(Codeforces & AtCoder 百套计划)
    SDWC2017游记
    非传统题初探——AtCoder Practice Contest #B
  • 原文地址:https://www.cnblogs.com/acioi/p/11724206.html
Copyright © 2020-2023  润新知