Loading

2022 ICPC合肥 G Game Plan

Game Plan

思维 && 环

考虑每个数字都作为一个点,每行同时出现就建一条双向边,形成若干个连通块

如果一个连通块是一颗树,则有该连通块中有个点必然取不到,直接贪心取最大值取不到即可

如果存在一个环,则该连通块中所有点都可以取到

#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <map>
#include <array>
#include <vector>
using namespace std;
const int maxn = 2e6 + 10;
int top[maxn];

int query(int x)
{
    return x == top[x] ? x : top[x] = query(top[x]);
}

int main()
{
    int n, m;
    cin >> n >> m;
    vector<array<int, 2>>num(m);
    for(int i=0; i<=2*m; i++) top[i] = i;
    int tp = 0;
    map<int, int>mp;
    vector<int>siz(2 * m + 1, 0), gsiz(2 * m + 1, 0), maxx(2 * m + 1, 0);
    vector<int>minn(2 * m + 1), to(2 * m + 1);
    for(int i=0; i<m; i++)
    {
        int a, b;
        cin >> a >> b;
        num[i] = {a, b};
        if(mp.count(a) == 0) {mp[a] = ++tp; to[tp] = a;}
        if(mp.count(b) == 0) {mp[b] = ++tp; to[tp] = b;}
        int aa = query(mp[a]), bb = query(mp[b]);
        if(aa != bb) top[aa] = bb;
    }
    for(auto [x, y] : num)
    {
        gsiz[query(mp[x])]++;
    }
    for(int i=1; i<=tp; i++)
    {
        siz[query(i)]++;
        maxx[query(i)] = max(maxx[query(i)], to[i]);
    }
    int ans = n + 1;
    for(int i=1; i<=n+1; i++) if(mp.count(i) == 0) {ans = i; break;}
    for(int i=1; i<=tp; i++)
    {
        if(i != query(i)) continue;
        if(gsiz[i] + 1 != siz[i]) continue;
        ans = min(ans, maxx[i]);
    }
    cout << ans << endl;
    return 0;
}
posted @ 2022-11-21 00:17  dgsvygd  阅读(209)  评论(0编辑  收藏  举报