Question
给定点权无向图,求任意由到
的路径中最大的第
小的点权。
Solution
二分答案,假设答案为,则对于第
小的点权,我们将其转化为该路径上有
的点,他们的点权值
。
我们将路径上的点染色分为两种点:
,染为
。
,染为
。
有如下情况:
一. 与
不联通,
二. 与
联通,
- 路径上存在两个连续的
号点,则显然我们可以通过反复横跳,来无限增大路径的长度,则必然能够满足使得
。
由于上面的情况已经除去,所以目前来说最好的情况是间隔,此时反复横跳已经没有任何意义。
a.,则所求点为中位数,由于首尾为
,所以
,
b.,则所求点为第
小的点权,
,
- 此时都有可能,我们DFS染色验证即可。
Code
#include <bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define lowbit(x) ((x) & -(x))
using namespace std;
using ll = long long;
using ull = unsigned long long;
using pii = pair<int, int>;
constexpr double eps = 1e-8;
constexpr int NINF = 0xc0c0c0c0;
constexpr int INF = 0x3f3f3f3f;
constexpr ll mod = 1e9 + 7;
constexpr ll N = 2e5 + 5;
int n, m, s, t, a[N];
vector<int> G[N];
bool vis[N], f[N];
void dfs(int u) {
vis[u] = true;
for (auto v : G[u]) {
if (!vis[v]) dfs(v);
}
}
void DFS(int u, int x) {
f[u] = true;
for (auto v : G[u]) {
if (!f[v] && max(a[u], a[v]) >= x) {
DFS(v, x);
}
}
}
bool check(int x) {
for (int i = 1; i <= n; i++) {
if (vis[i] && a[i] >= x) {
for (auto j : G[i]) {
if (a[j] >= x) return true;
}
}
}
if (a[s] < x && a[t] < x) return false;
memset(f, 0, sizeof(f));
DFS(s, x);
return f[t];
}
void solve() {
cin >> n >> m >> s >> t;
for (int i = 1; i <= n; i++) {
cin >> a[i];
G[i].clear();
vis[i] = false;
}
for (int i = 1; i <= m; i++) {
int u, v;
cin >> u >> v;
G[u].push_back(v);
G[v].push_back(u);
}
dfs(s);
if (!vis[t]) {
cout << "NO\n";
return;
} else {
cout << "YES\n";
}
int L = 0, R = *max_element(a + 1, a + 1 + n) + 1, ans = 0;
while (L < R) {
int mid = (L + R) / 2;
if (check(mid)) {
ans = mid;
L = mid + 1;
} else {
R = mid;
}
}
cout << ans << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;
cin >> T;
while (T--) {
solve();
}
return 0;
}Solution Update
经评论区提醒做出如下修改,反而没跑过去,我怀疑题目的数据是错的。
#include <bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define lowbit(x) ((x) & -(x))
using namespace std;
using ll = long long;
using ull = unsigned long long;
using pii = pair<int, int>;
constexpr double eps = 1e-8;
constexpr int NINF = 0xc0c0c0c0;
constexpr int INF = 0x3f3f3f3f;
constexpr ll mod = 1e9 + 7;
constexpr ll N = 2e5 + 5;
int n, m, s, t, a[N];
vector<int> G[N];
int f[N];
bool vis[N];
void dfs(int u) {
vis[u] = true;
for (auto v : G[u]) {
if (!vis[v]) dfs(v);
}
}
void DFS1(int u, int x) {
f[u] = 1;
for (auto v : G[u]) {
if (!f[v] && max(a[u], a[v]) >= x) {
DFS1(v, x);
}
}
}
void DFS2(int u, int x) {
if (f[u] == 1) {
f[t] = 1;
return;
}
f[u] = 2;
for (auto v : G[u]) {
if (f[v] != 2 && (f[v] == 1 || max(a[u], a[v]) >= x)) {
DFS2(v, x);
}
}
}
bool check(int x) {
for (int i = 1; i <= n; i++) {
if (vis[i] && a[i] >= x) {
for (auto j : G[i]) {
if (a[j] >= x) return true;
}
}
}
if (a[s] < x && a[t] < x) return false;
memset(f, 0, sizeof(f));
DFS1(s, x);
DFS2(t, x);
return f[t] == 1;
}
void solve() {
cin >> n >> m >> s >> t;
for (int i = 1; i <= n; i++) {
cin >> a[i];
G[i].clear();
vis[i] = false;
}
for (int i = 1; i <= m; i++) {
int u, v;
cin >> u >> v;
G[u].push_back(v);
G[v].push_back(u);
}
dfs(s);
if (!vis[t]) {
cout << "NO\n";
return;
} else {
cout << "YES\n";
}
int L = 0, R = *max_element(a + 1, a + 1 + n) + 1, ans = 0;
while (L < R) {
int mid = (L + R) / 2;
if (check(mid)) {
ans = mid;
L = mid + 1;
} else {
R = mid;
}
}
cout << ans << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;
cin >> T;
while (T--) {
solve();
}
return 0;
}
京公网安备 11010502036488号