泥豪!我是2789617221guo!欢|

2789617221guo

园龄:1个月粉丝:2关注:2

2025-03-01 22:10阅读: 2评论: 0推荐: 0

洛谷P1396 营救 题解

本题做法

  • 二分答案+BFS。

思路

对于输入的数据,使用4个数组\(head,tail,value,next\)记录每个点的第一条边、每条边的结尾、每条边的拥挤值以及每条边的下一条边。

随后使用二分答案法二分所求的答案,使用\(check\)函数检测是否可行。

\(check\)函数:从\(s\)点开始BFS,若当前边的\(value\)小于等于\(x\),则将当前边的\(tail\)加入队列,继续BFS。最后,判断是否走过\(t\)点,若走过,则返回true;否则返回false。

代码

#include <bits/stdc++.h>
#define endl '\n'
#define ll long long
using namespace std;
const int INF = 0x3f3f3f3f;
const double EPS = 1e-8;
const int N = 2e5 + 5;
int n, m, s, t, u, v, w, mxw = -1;
int value[N], /*表示第i条边的拥挤度*/ head[N], /*表示第i个点的第一条边*/
tail[N], /*表示第i条边的*/ nxt[N]; /*表示第i条边的下一条边*/
bool vis[N];
bool check(int x) {
memset(vis, 0, sizeof(vis));
queue<int> q;
vis[s] = 1;
q.push(s);
while (!q.empty()) {
int stt = head[q.front()];
q.pop();
while (stt) {
if (value[stt] <= x && !vis[tail[stt]]) {
q.push(tail[stt]);
vis[tail[stt]] = 1;
}
stt = nxt[stt];
}
}
return vis[t];
}
int main() {
cin >> n >> m >> s >> t;
for (int i = 1; i <= m; i++) {
cin >> u >> v >> w;
// 从u到v的边
value[2 * i] = w;
tail[2 * i] = v;
nxt[2 * i] = head[u];
head[u] = 2 * i;
// 从v到u的边
value[2 * i + 1] = w;
tail[2 * i + 1] = u;
nxt[2 * i + 1] = head[v];
head[v] = 2 * i + 1;
mxw = max(mxw, w);
}
if (s == t) {
cout << 0 << endl;
return 0;
}
int l = 0, r = mxw + 1;
while (l + 1 < r) {
int mid = l + (r - l) / 2;
if (check(mid))
r = mid;
else
l = mid;
}
cout << r << endl;
return 0;
}

本文作者:2789617221guo

本文链接:https://www.cnblogs.com/2789617221guo/p/18745507

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   2789617221guo  阅读(2)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起