2493.将节点分成尽可能多的组
链接:2493.将节点分成尽可能多的组
难度:Hard
标签:广度优先搜索、并查集、图
简介:请你返回最多可以将节点分为多少个组(也就是最大的 m )。如果没办法在给定条件下分组,请你返回 -1 。
题解 1 - cpp
- 编辑时间:2022-12-04
- 执行用时:1960ms
- 内存消耗:141.3MB
- 编程语言:cpp
- 解法介绍:先通过并查集区分不同的连通图,对每个连通图的每个点进行枚举 bfs 判断对长组。
#include <iostream>
#include <vector>
// bestlyg
# define X first
# define Y second
# define lb(x) ((x) & (-x))
# define mem(a,b) memset(a,b,sizeof(a))
# define debug freopen("r.txt","r",stdin)
# define pi pair<int,int>
#ifdef DEBUG
#define log(frm, args...) {    printf(frm, ##args); }
#else
#define log(frm, args...)
#endif
typedef long long ll;
using namespace std;
class UnionFind {
public:
    int n;
    vector<int> list;
    UnionFind(int n): n(n) {
        list = vector<int>(n);
        for (int i = 0; i < n; i++) list[i] = i;
    }
    int find(int v) {
        if (list[v] == v) return v;
        return list[v] = find(list[v]);
    }
    void uni(int v1, int v2) {
        int p1 = find(v1), p2 = find(v2);
        if (p1 != p2) list[p1] = p2;
    }
};
class Node {
public:
    int v;
    unordered_set<int> next;
};
class Solution {
public:
    int magnificentSets(int n, vector<vector<int>>& edges) {
        vector<Node> list(n);
        UnionFind uf(n);
        for (int i = 0; i < n; i++) list[i].v = i;
        for (auto &edge : edges) {
            int v1 = edge[0] - 1, v2 = edge[1] - 1;
            list[v1].next.insert(v2);
            list[v2].next.insert(v1);
            uf.uni(v1, v2);
        }
        auto comp = [&](int start){
            // cout << "====" << start << endl;
            queue<int> q;
            q.push(start);
            unordered_set<int> used;
            unordered_map<int, unordered_set<int>> m;
            int level = 0, size = 1;
            used.insert(start);
            m[0].insert(start);
            while (q.size()) {
                int cur = q.front();
                // cout << "cur = " << cur << ", level = " << level << endl;
                q.pop();
                for (auto &next : list[cur].next) {
                    // cout << "next = " << next << ", " << used.count(next) << endl;
                    if (used.count(next)) {
                        if (m[level - 1].count(next) || m[level + 1].count(next)) continue;
                        else return -1;
                    }
                    used.insert(next);
                    m[level + 1].insert(next);
                    q.push(next);
                }
                if (--size == 0) {
                    size = q.size();
                    level++;
                }
            }
            return level;
        };
        unordered_map<int, int> m;
        for (int i = 0; i < n; i++) {
            int p = uf.find(i), v = comp(i);
            if (v == -1) return -1;
            m[p] = max(m[p], v);
        }
        int ans = 0;
        for (auto &item : m) ans += item.Y;
        return ans;
    }
};