洛谷 P1462 通往奥格瑞玛的道路 (最短路+二分)

洛谷 P1462 通往奥格瑞玛的道路

题目传送

无数发wa之后终于过了。
方法:dijkstral+二分
详解:将过路费排列后枚举,判断是否可行。以伤害作为边的权值,找最短路,并判断血量是否足够。
二分之前,先用最大路费判断,若最大路费都不可通过,则无解。

#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#define maxn 10000+10
#define maxm 50010
#define inf 1000000000+100
using namespace std;

struct edgs { //边
	int from, to, cost, next;
} edg[maxm * 2];

struct node { //作为队列的类型
	int d, u;
	node(int a, int b) :d(a), u(b) {}
	bool operator<(const node& p) const {
		return d > p.d;
	}
};

int n, m, tot, cnt;
int f[maxn], an[maxn]; //费用
int d[maxn]; //血
int used[maxn]; //标记
int head[maxn]; //邻接矩阵头

void addedgs(int from, int to, int cost)
{
	cnt++;
	edg[cnt].from = from;
	edg[cnt].to = to;
	edg[cnt].cost = cost;
	edg[cnt].next = head[from];
	head[from] = cnt;
	return;
}

bool cheak(int top)
{
	if (f[1] > top || f[n] > top) return false;
	for (int i = 1; i <= n; i++) {
		d[i] = inf;
		used[i] = 0;
	}
	d[1] = 0;
	priority_queue<node> q;
	q.push(node(0, 1));
	while (q.size()) {
		int u = q.top().u;
		q.pop();
		if (used[u]) continue;
		used[u] = 1;
		for (int i = head[u]; i; i = edg[i].next) {
			if (d[edg[i].to] > d[u] + edg[i].cost && f[edg[i].to] <= top) {
				d[edg[i].to] = d[u] + edg[i].cost;
				q.push(node(d[edg[i].to], edg[i].to));
			}
		}
	}
	if (d[n] <= tot) return true;
	else return false;
}

int main(void)
{
	ios::sync_with_stdio(false);
	cin >> n >> m >> tot;
	for (int i = 1; i <= n; i++) {
		cin >> f[i];
		an[i] = f[i];
	}
	sort(an + 1, an + n + 1);
	for (int i = 1; i <= m; i++) {
		int a, b, c;
		cin >> a >> b >> c;
		addedgs(a, b, c);
		addedgs(b, a, c);
	}
	if (cheak(an[n]) == false) { //判断最大费用能否到达
		cout << "AFK";
		return 0;
	}
	int l = 1, r = n, ans = an[n];
	while (l <= r) { //二分
		int mid = (l + r) / 2;
		if (cheak(an[mid])) {
			ans = an[mid];
			r = mid - 1;
		}
		else l = mid + 1;
	}
	cout << ans;
	return 0;
}
发布了16 篇原创文章 · 获赞 9 · 访问量 4576

猜你喜欢

转载自blog.csdn.net/qq_43054573/article/details/104129778
今日推荐