zoukankan      html  css  js  c++  java
  • P1462 通往奥格瑞玛的道路(二分+dijkstra)

    题目背景

    在艾泽拉斯大陆上有一位名叫歪嘴哦的神奇术士,他是部落的中坚力量
    有一天他醒来后发现自己居然到了联盟的主城暴风城
    在被众多联盟的士兵攻击后,他决定逃回自己的家乡奥格瑞玛

    题目描述

    在艾泽拉斯,有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。

    二分答案,每次跑一边dijkstra,如果如果某一个城市的收费大于二分的值就跳过它。最后到n的最短路小于b即为合法。
    下面代码:

    #include<bits/stdc++.h>
    #define ll long long
    #define pii pair<ll,int>
    using namespace std;
    
    ll n,m,b,f[10010];
    struct Edge{
    	int to,next;
    	ll w;
    }edge[100010];
    int h[10010],tot;
    void add(int u,int v,ll w){
    	edge[++tot].w = w;
    	edge[tot].to = v;
    	edge[tot].next = h[u];
    	h[u] = tot; 
    }
    priority_queue<pii> q;
    ll vis[10010],dis[10010]; 
    ll dijk(ll mid){
    	for(int i = 1; i <= n; ++i){
    		dis[i] = 0x3f3f3f3f;
    		vis[i] = 0;
    	}
    	dis[1] = 0;
    	q.push(make_pair(0,1));
    	while(!q.empty()){
    		int p = q.top().second;
    		q.pop();
    		if(vis[p]) continue;
    		vis[p] = 1;
    		for(int i = h[p]; i; i = edge[i].next){
    			int v = edge[i].to;
    			if(f[v] > mid) continue;
    			if(dis[v] > dis[p] + edge[i].w){
    				dis[v] = dis[p] + edge[i].w;
    				if(!vis[v]) q.push(make_pair(-dis[v],v));
    			}
    		}
    	}
    	return dis[n];
    }
    
    int main(){
    	cin >> n >> m >> b;
    	ll l = 0,r = 0; 
    	for(int i = 1; i <= n; ++i){
    		scanf("%lld",&f[i]);
    		r = max(r,f[i]);
    	}
    	for(int i = 1; i <= m; ++i){
    		int a,b; ll c;
    		scanf("%d%d%lld",&a,&b,&c);
    		add(a,b,c);
    		add(b,a,c);
    	}
    	if(dijk(r) >= b){
    		cout << "AFK" << endl;
    		return 0;
    	}
    	while(l < r){
    		ll mid = (l + r) >> 1;
    		if(dijk(mid) < b) r = mid;
    		else l = mid + 1;
    	}
    	cout << l << endl;
    	return 0;
    }
    
  • 相关阅读:
    vue使用elementui合并table
    使用layui框架导出table表为excel
    vue使用elementui框架,导出table表格为excel格式
    前台传数据给后台的几种方式
    uni.app图片同比例缩放
    我的博客
    【C语言】取16进制的每一位
    SharePoint Solution 是如何部署的呢 ???
    无效的数据被用来用作更新列表项 Invalid data has been used to update the list item. The field you are trying to update may be read only.
    SharePoint 判断用户在文件夹上是否有权限的方法
  • 原文地址:https://www.cnblogs.com/FoxC/p/11379767.html
Copyright © 2011-2022 走看看