luogu P5631 最小mex生成樹
阿新 • • 發佈:2021-12-17
https://www.luogu.com.cn/problem/P5631
類似SUM那題
挖掉某一塊後看是否還是能構成生成樹
考慮分治,用按秩合併並查集來維護聯通性
code:
#include<bits/stdc++.h> #define N 2000050 using namespace std; struct E { int u, v, c; } e[N]; int cmp(E x, E y) { return x.c < y.c; } int fa[N], siz[N], n, m; int get(int x) { return fa[x] == x ? x : get(fa[x]); } int merge(int x, int y) { x = get(x), y = get(y); if(x == y) return 0; if(siz[x] > siz[y]) swap(x, y); fa[x] = y, siz[y] += siz[x]; return x; } void del(int x) { siz[fa[x]] -= siz[x]; fa[x] = x; } void cdq(int l, int r, int L, int R) { if(l == r) { //if(l == e[m].c + 1) printf("%d ", siz[get(1)]); if(siz[get(1)] == n) { printf("%d", l); exit(0); } return ; } vector<int> sta; int mid = (l + r) >> 1, pos = R; while(pos >= L && e[pos].c > mid) sta.push_back(merge(e[pos].u, e[pos].v)), pos --; cdq(l, mid, L, pos); while(sta.size()) del(sta.back()), sta.pop_back(); sta.clear(); for(int i = L; i <= pos; i ++) sta.push_back(merge(e[i].u, e[i].v)); cdq(mid + 1, r, pos + 1, R); while(sta.size()) del(sta.back()), sta.pop_back(); sta.clear(); } int main() { scanf("%d%d", &n, &m); for(int i = 1; i <= m; i ++) scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].c); for(int i = 1; i <= n; i ++) fa[i] = i, siz[i] = 1; sort(e + 1, e + 1 + m, cmp); cdq(0, e[m].c + 1, 1, m); return 0; }