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;
}