• 洛谷P1462 通往奥格瑞玛的道路(SPFA+二分答案)


    题目背景

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

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

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

    题目描述

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

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

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

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

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

    输入格式

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

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

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

    输出格式

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

    如果他无法到达奥格瑞玛,输出( ext{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 le 200,m le 10^4,b le 200)

    对于(100%)的数据,满足(n le 10^4)(m le 5 imes 10^4)(b le 10^9),满足(c_i le10^9,f_i le 10^9)可能有两条边连接着相同的城市。

    血量为0的时候,视为可以通过.


    解题报告

    题意理解

    这道题目,让我们满足两个条件.

    1. 血量充足,也就是路径消耗要小于血量最大值.

    2. 这条路径上经过的点,最大点权最小.

    3. 从起点到终点


    算法解析

    如果说排除,血量因素,这道题目是非常显然的最短路径问题.

    但是我们现在多了一个限制条件,那么该如何是好?

    我们知道,如果说我们的最终答案(x_1),也就是说答案路径上最大点的点权(x_1).

    现在有一个值(x_2),表示限制目标答案路径上最大点的点权为(x_2)

    [若x_1<x_2,显然x_2这个条件是可以满足的 ]

    同理,我们也可以推断出.

    [若x_1>x_2,显然x_2这个条件是无法满足的,因为题目的答案是x_1,而不是x_2. ]

    综上所述,我们不难得出结论.

    这道题目可以,二分最大点权,也就是二分答案

    既然如此,我们的判断(check)函数,如何处理呢?

    我们可以用最短路算法作为判断.以血量作为权值.

    转移,则是满足.这条边抵达的终点(y),需要满足(y<=mid)

    然后这道题目就这样解决了.


    代码解析

    #include <bits/stdc++.h>
    using namespace std;
    const int N=1e4+20,M=5e4+20;
    #define int long long//这道题目数据范围有点大,所以为了抱歉,我们选择long long
    int n,m,b,f[N],l,r,head[M],edge[M<<1],Next[M<<1],ver[M<<1],tot,vis[N],dis[N];
    inline int Spfa(int mid)
    {
    	memset(vis,false,sizeof(vis));
    	memset(dis,0x3f,sizeof(dis));
    	queue<int> q;
    	q.push(1);
    	dis[1]=0;
    	if (f[1]>mid)//初始点也要判断
    		return false;
    	while(q.size())
    	{
    		int now=q.front();
    		q.pop();
    		vis[now]=false;
    		for(int i=head[now]; i; i=Next[i])
    		{
    			int y=edge[i],w=dis[now]+ver[i];
    			if (dis[y]>w && f[y]<=mid)//目标点点权不可以大于限制值
    			{
    				dis[y]=w;
    				if (!vis[y])
    				{
    					q.push(y);
    					vis[y]=1;
    				}
    			}
    		}
    	}
    	return dis[n]<=b;//需要满足血量花费不可以大于最大花费
    }
    inline void add_edge(int a,int b,int c)
    {
    	edge[++tot]=b;
    	ver[tot]=c;
    	Next[tot]=head[a];
    	head[a]=tot;
    }
    inline void init()
    {
    	scanf("%lld%lld%lld",&n,&m,&b);
    	for(int i=1; i<=n; i++)
    	{
    		scanf("%lld",&f[i]);
    		r=max(f[i],r);//最大点权
    	}
    	for(int i=1; i<=m; i++)
    	{
    		int a,b,c;
    		scanf("%lld%lld%lld",&a,&b,&c);
    		add_edge(a,b,c);
    		add_edge(b,a,c);//建立无向图
    	}
    	while(l<r)//二分
    	{
    		int mid=l+r>>1;
    		if (Spfa(mid))
    			r=mid;
    		else
    			l=mid+1;
    	}
    	if (!Spfa(r))//无解
    		puts("AFK");
    	else
    		printf("%lld
    ",r);
    }
    signed main()
    {
    	init();
    	return 0;
    }
    
  • 相关阅读:
    PHP openssl_encrypt函数安全漏洞
    WordPress Organizer插件安全漏洞
    WordPress Poll插件多个SQL注入和安全绕过漏洞
    Redis 重写任意文件漏洞
    WordPress Events Manager插件多个跨站脚本漏洞
    项目建议书编写总结
    www.beihua.edu.cn计划摘录
    《易经》对中华文化的影响
    网站调研资料记录
    积分和排名
  • 原文地址:https://www.cnblogs.com/gzh-red/p/11801740.html
Copyright © 2020-2023  润新知