CF1494D

· · 题解

并查集做法

O(5\times10^3\times n^2)

思路比较简单:

我们从叶子往根考虑,把点合并(一开始任何点都是独立的):

补充:

CODE:

#include <iostream>
#include <vector>
using namespace std;

constexpr size_t MAXN = 1e3 + 5, MAXM = 5e3 + 5;
typedef pair<int, int> pii;
int a[MAXN][MAXN], f[MAXN], dad[MAXN];
int n, k;
vector<pii> v[MAXM];

int Find(int x) { return f[x] == x ? x : f[x] = Find(f[x]); }

signed main() {
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin >> n, k = n;
    for (int i = 1; i < MAXN; i++) f[i] = i;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++) {
            cin >> a[i][j];
            if (i < j) v[a[i][j]].push_back({ i,j });
        }
    for (int i = 0; i < MAXM; i++) {
        for (int j = v[i].size() - 1; j >= 0; j--) {
            int fx = Find(v[i][j].first), fy = Find(v[i][j].second);
            if (a[fx][fx] < a[fy][fy])
                swap(fx, fy);
            if (a[fx][fx] == i)
                dad[fy] = fx, f[fy] = fx;
            else
                k++, a[k][k] = i, dad[fx] = k, dad[fy] = k, f[fx] = k, f[fy] = k;
        }
    }
    cout << k << '\n';
    for (int i = 1; i <= k; i++) cout << a[i][i] << ' ';
    cout << '\n' << k << '\n';
    for (int i = 1; i < k; i++) cout << i << ' ' << dad[i] << '\n';
}