L - Session in BSU

传送门

题意:
有n场考试,给出每场考试的\(a_i, b_i\)值, \(a_i < b_i\), \(a_i, b_i\)代表这场考试可以考的时间,问最少需要多少天来考完n场考试,如果不能考完就输出-1


思路:
先介绍一下整体思路,将\(a_i, b_i\)连边,连通块里面的边和点的情况可以分为3中情况

  • 边 == 点数,对于这种情况,取里面的最大值
  • 边 == 点数 + 1,对于这种情况,取次大值
  • 边 > 点数,对于这种情况是不可能的,直接输出-1

对于这种两个两个联动,考虑下并查集,就用并查集来实现一个连边的操作, 这里用到了连通块的思想,连通块图论可以处理,并查集也可以处理, 然后边 == 点数,可以用一个tag标记来实现,边数 > 点数,那就是在已经有环的基础上,又有一个环,还是用tag来标记实现,求每个点的最大值和最小值,可以利用类似dp的思想,先赋初值,然后在在求解, 最后ans再取最大值即可


总结:
并查集判断实现边点关系,求一个连通块中的最大值和次大值

点击查看代码
#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(false);
#define endl '\n'
using namespace std;

typedef long long ll;
const ll MAXN = 1e6 + 10;
ll n;
ll fa[MAXN << 1], firmx[MAXN << 1], secmx[MAXN << 1], tag[MAXN << 1];
struct Node
{
    ll a, b;
} w[MAXN];

ll find(ll x)
{
    return x == fa[x] ? x : fa[x] = find(fa[x]);
}

int main()
{
    IOS; cin.tie(0), cout.tie(0);
    cin >> n;
    vector<ll> num;
    for (int i = 0, a, b; i < n; ++i)
    {
        cin >> w[i].a >> w[i].b;
        num.emplace_back(w[i].a);
        num.emplace_back(w[i].b);
    }
    sort(num.begin(), num.end());
    auto newend = unique(num.begin(), num.end());
    num.erase(newend, num.end());
    for (int i = 0; i < n; ++i)
    {
        w[i].a = lower_bound(num.begin(), num.end(), w[i].a) - num.begin();
        w[i].b = lower_bound(num.begin(), num.end(), w[i].b) - num.begin();
    }
    for (int i = 0; i < num.size(); ++i)
        fa[i] = i, firmx[i] = num[i];
    for (int i = 0; i < n; ++i)
    {
        ll u = find(w[i].a), v = find(w[i].b);
        if (u != v)
        {
            fa[v] = u, tag[u] |= tag[v];
            if (firmx[v] > firmx[u])
                secmx[u] = max(secmx[v], firmx[u]), firmx[u] = firmx[v];
            else
                secmx[u] = max(secmx[u], firmx[v]);     
        }
        else if (tag[u])
            puts("-1"), exit(0);
        else
            tag[u] = 1;
        
    }    
    ll ans = 0;
    for (int i = 0; i < num.size(); ++i)
        {
            if (i == find(i))
            {
                if (tag[i])
                    ans = max(ans, firmx[i]);
                else
                    ans = max(ans, secmx[i]);    
            }
        }        
        cout << ans << endl;
    return 0;
}

posted @ 2022-10-16 16:29  YUGUOTIANQING  阅读(23)  评论(0)    收藏  举报