NC9985A美丽的路径

美丽的路径

https://ac.nowcoder.com/acm/contest/9985/A

Question

给定点权无向图,求任意由的路径中最大的第小的点权。

Solution

二分答案,假设答案为,则对于第小的点权,我们将其转化为该路径上有的点,他们的点权值
我们将路径上的点染色分为两种点:

  1. ,染为
  2. ,染为

有如下情况:
一. 不联通,
二. 联通,

  1. 路径上存在两个连续的号点,则显然我们可以通过反复横跳,来无限增大路径的长度,则必然能够满足使得

  2. 由于上面的情况已经除去,所以目前来说最好的情况是间隔,此时反复横跳已经没有任何意义。
    a. ,则所求点为中位数,由于首尾为,所以
    b. ,则所求点为第小的点权,
  3. 此时都有可能,我们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;
}
11eyes的排位日记 文章被收录于专栏

codeforces近期的比赛2200以下的题目为主的一些各大OJ平台的题

全部评论
第三种情况代码错了,Hack数据: 1 4 3 1 4 4 2 1 6 1 2 2 3 3 4 答案为4 代码输出2
1 回复 分享
发布于 2021-03-09 10:13

相关推荐

有没有友友知道hr面会问什么我应该反问什么?还有如何防止hr套话啊?还有应该如果催hr推进快一点#字节#OPPO#hr面
牛客989988346号:职业规划,优缺点,为什么选择这个岗,对应聘公司产品的了解和满意度,如果让你改进公司产品你会怎么做,对ai(新技术)的了解,有无其他offer,什么时候能到岗
点赞 评论 收藏
分享
米黑子米黑子:你这个成绩不争取下保研?
点赞 评论 收藏
分享
小厂面经,也是我的处女面(30min)1.自我介绍2.spring&nbsp;boot的自动装配原理(好多类和接口的单词都忘了全称是啥了,就说了记得的单词,流程应该说对了吧)3.有用过redis吗?主要是用在实现什么功能(说了技术派用redis的zset来实现排行榜)5.有了解过Redisson吗?讲一下对于分布式锁的了解以及在什么场景下应用(说了秒杀场景)6.对mysql有了解吗?包括它的索引优化和创建(把想起来的全说了)7.了解设计模式吗?比如单例模式,为什么要使用单例模式,它的优点是什么(昨天刚看的设计模式)8.工厂模式有了解吗?主要的使用场景是?(也是昨天刚看的)9.场景题:有7个服务器,需要在早上十点定时的向数据库中的用户表中的用户发短信,如果做到发送的消息不重复,且如果发送失败了需要知道是到哪个用户失败了,这样下次就直接从这个用户开始(我答了用spring&nbsp;task来实现定时,用分布式锁来保证只有一份服务器可以发送消息,用消息队列来存储消息,然后用消息确认机制来保证错误信息的记录,以及在数据库或者业务层面完成消息消费的幂等性)10.场景题:如果在系统启动的时间就将数据库的所有用户相关的信息都读到一个hashmap中(这个没啥思路,没答好)27届的投了一个星期终于有一个面试了,大部分公司都只招26的
inari233:已oc,拒了
查看9道真题和解析
点赞 评论 收藏
分享
评论
4
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务