2022合肥站 G-Game Plan

思路:

(1)条件:

  1. 给定1~n 数字;(n达到1e9)
  2. 给出t天,每天给两个数字选1个删除;t范围1e5

(2)问题:在最后没删的数字中最小值最大的条件下,求此最小值;

(3)分析:

  1. 首先,要让没删的数字最小值最大,则尽量删小的;
  2. 能删一定要删;
  3. 每次连接可能删除的两个数字,当其构成环时,就能全部删除;
  4. 若不构成环,则保留最大值不删;

(4)算法实现:

  1. 存图;
  2. 对于有环图,全部删除,对于无环图,除最大值外全部删除;
  3. 第二步可优化为,图上节点全部删除,对于无环最大值保留;
  4. 遍历1~n找到未删节点最小值;
  5. 由于讨论1~n必然超时,注意到最多删除t个数,答案最大也就是t+1,所以只用讨论1~t+1即可;

(5)具体实现:

  1. 存图有很多种办法,此处要快速区分不同图集,对于每个图集还要判环,可在建图过程中考虑并查集;
  2. 输入点时判断,若已经是同一祖宗,即含有环,祖宗标记为1,否则添加新点,由于无环祖宗为1,有环祖宗为0,认祖宗时,新祖宗继承旧祖宗标记;注意将这些点删除,标记为1;
  3. 此时有环祖宗标记为1,无环为0;逐点判断,若祖宗为0 ,更新该祖宗对应的最大值;
  4. 对于所有最大值,再度保留,标记为0;
  5. 从1~t逐一判断,若某值第一个为0,输出结束即可;

代码:

#include 
using namespace std;
 
typedef long long ll;
#define int ll
#define endl '\n'
 
const int inf = 0x3f3f3f3f3f3f3f3f;
const int N = 1e6 + 10;
 
int dad[N], a[N], n, t, col[N];
unordered_mapmp;
int getfa(int x) {
    return x == dad[x] ? x : dad[x] = getfa(dad[x]);
}
signed main() {
    ios::sync_with_stdio(false);
    cin >> n >> t;
    for (int i = 1; i <= t; i++) dad[i] = i;
    for (int i = 1; i <= t; i++) {
 
        int x, y;
        cin >> x >> y;
        if (x > y) swap(x, y);
        if (x > t) continue;
        if (y > t) y = x;
        a[x]= a[y] = 1;
        int xx = getfa(x), yy = getfa(y);
 
        if (xx == yy) {
            col[yy] = 1;
            continue;
        }
        if(xx != yy) {
            dad[xx] = yy;
            col[yy] = max(col[yy], col[xx]);
            col[xx] = max(col[yy], col[xx]);
        }
    }
    for (int i = 1; i <= t; i++) {
        int x = getfa(i);
        //cout<

你可能感兴趣的:(算法)