zoukankan      html  css  js  c++  java
  • 洛谷 P1462 通往奥格瑞玛的道路 题解

    P1462 通往奥格瑞玛的道路

    题目背景

    在艾泽拉斯大陆上有一位名叫歪嘴哦的神奇术士,他是部落的中坚力量

    有一天他醒来后发现自己居然到了联盟的主城暴风城

    在被众多联盟的士兵攻击后,他决定逃回自己的家乡奥格瑞玛

    题目描述

    在艾泽拉斯,有n个城市。编号为1,2,3,...,n。

    城市之间有m条双向的公路,连接着两个城市,从某个城市到另一个城市,会遭到联盟的攻击,进而损失一定的血量。

    每次经过一个城市,都会被收取一定的过路费(包括起点和终点)。路上并没有收费站。

    假设1为暴风城,n为奥格瑞玛,而他的血量最多为b,出发时他的血量是满的。

    歪嘴哦不希望花很多钱,他想知道,在可以到达奥格瑞玛的情况下,他所经过的所有城市中最多的一次收取的费用的最小值是多少。

    输入格式

    第一行3个正整数,n,m,b。分别表示有n个城市,m条公路,歪嘴哦的血量为b。

    接下来有n行,每行1个正整数,fi。表示经过城市i,需要交费fi元。

    再接下来有m行,每行3个正整数,ai,bi,ci(1<=ai,bi<=n)。表示城市ai和城市bi之间有一条公路,如果从城市ai到城市bi,或者从城市bi到城市ai,会损失ci的血量。

    输出格式

    仅一个整数,表示歪嘴哦交费最多的一次的最小值。

    如果他无法到达奥格瑞玛,输出AFK。

    输入输出样例

    输入 #1

    4 4 8
    8
    5
    6
    10
    2 1 2
    2 4 1
    1 3 4
    3 4 3

    输出 #1

    10

    说明/提示

    对于60%的数据,满足n≤200,m≤10000,b≤200

    对于100%的数据,满足n≤10000,m≤50000,b≤1000000000

    对于100%的数据,满足ci≤1000000000,fi≤1000000000,可能有两条边连接着相同的城市。

    【思路】

    最短路 + dijkstra + 二分答案

    【题目大意】

    走每一条路都会消耗一定的血量
    到每一个城市都会话费一定的金钱
    求在活着的情况下经过的城市中交的金钱最多的最少

    【题目分析】

    【二分】

    使最多的最少
    很显然在提示你要用二分答案
    二分有两个选择:
    1.二分血量
    2.二分花费最多的城市花的钱
    如果二分血量
    那处理起来就相当麻烦了
    但是如果二分花费
    限制了哪些城市不能走
    这样就可以check在限制之外的城市中能不能活着到达目的地

    【最短路】

    看活着的情况
    经过的路径血量消耗不等大于等于歪嘴哦的血量
    注意:
    即使是等于也是不行的
    这样的话在二分的前提之下(只走花费不超过二分值的城市)
    要让消耗的血量最少
    而且消耗的血量是依附于某条路径的
    所以可以当成路径的权值来跑

    【核心思路】

    二分花费最高城市的花费
    然后跑dijkstra
    因为有了最高花费的限制
    所以花费超出二分值的城市就不能够被进行松弛操作
    用剩下的跑一下最短路
    看看最后1-n的最少消耗的血量是不是小于歪嘴哦的血量
    如果小于那就返回真
    反之返回假

    【完整代码】

    #include<iostream> 
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #define int long long
    using namespace std;
    
    int read()
    {
    	int sum = 0,fg = 1;
    	char c = getchar();
    	while(c < '0' || c > '9')
    	{
    		if(c == '-')fg = -1;
    		c = getchar();
    	}
    	while(c >= '0' && c <= '9')
    	{
    		sum = sum * 10 + c - '0';
    		c = getchar();
    	}
    	return sum * fg; 
    }
    const int Max = 10004;
    int f[Max];
    struct node
    {
    	int y,ne;
    	int z;
    }a[Max * 10];
    int head[Max],sum = 0;
    void add(int x,int y,int z)
    {
    	a[++ sum].y = y;
    	a[sum].ne = head[x];
    	a[sum].z = z;
    	head[x] = sum;
    }
    
    struct point
    {
    	int x;
    	int w;
    	bool operator < (const point xx) const 
    	{
    		return xx.w < w;
    	}
    };
    int dis[Max];
    bool use[Max];
    priority_queue<point>q;
    int n,m,hp;
    bool check(int mid)
    {
    	memset(dis,0x3f,sizeof(dis));
    	memset(use,false,sizeof(use));
    	dis[1] = 0;
    	q.push((point){1,0});
    	while(!q.empty())
    	{
    		int x = q.top().x;
    		q.pop();
    		if(use[x] == true)
    			continue;
    		use[x] = true;
    		for(register int i = head[x];i != 0;i = a[i].ne)
    		{
    			int awa = a[i].y;
    			if(dis[awa] > dis[x] + a[i].z && f[awa] <= mid)
    			{
    				dis[awa] = dis[x] + a[i].z;
    				if(use[awa] == false)
    					q.push((point){awa,dis[awa]});
    			}
    		}
    	}
    	if(dis[n] < hp)
    		return true;
    	return false;
    }
    
    signed main()
    {
    	n = read(),m = read(),hp = read();
    	int r = 0;
    	for(register int i = 1;i <= n;++ i)
    		f[i] = read(),r = max(r,f[i]);
    	for(register int i = 1;i <= m;++ i)
    	{
    		int x = read(),y = read(),z = read();
    		add(x,y,z);
    		add(y,x,z);
    	}
    	int qwq = r;
    	r ++;
    	int l = 0;
    	while(l < r)
    	{
    		int mid = (r + l) >> 1;
    		if(check(mid))r = mid;
    		else	l = mid + 1;
    	}
    	if(l == qwq + 1)
    	{
    		cout << "AFK" << endl;
    		return 0;
    	}
    	cout << l << endl;
    	return 0;
    }
    
  • 相关阅读:
    Linux内核网络协议栈优化总纲
    Java实现 蓝桥杯VIP 算法训练 连续正整数的和
    Java实现 蓝桥杯VIP 算法训练 连续正整数的和
    Java实现 蓝桥杯VIP 算法训练 寂寞的数
    Java实现 蓝桥杯VIP 算法训练 寂寞的数
    Java实现 蓝桥杯VIP 算法训练 学做菜
    Java实现 蓝桥杯VIP 算法训练 学做菜
    Java实现 蓝桥杯VIP 算法训练 判断字符位置
    Java实现 蓝桥杯VIP 算法训练 判断字符位置
    Java实现 蓝桥杯VIP 算法训练 链表数据求和操作
  • 原文地址:https://www.cnblogs.com/acioi/p/11822897.html
Copyright © 2011-2022 走看看