1 条题解

  • 0
    @ 2025-8-24 23:10:33

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar 水星湖

    搬运于2025-08-24 23:10:33,当前版本为作者最后更新于2025-03-02 10:59:23,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    必然有解。

    当图中有 2\ge 2 个连通块时,将较小的连通块内所有点放在第一类,剩下大的连通块大小必然 2\ge 2,任取一个点作为第二类,剩下的作为第三类,显然合法。

    否则,当图中仅有一个连通块时,由于 m2n4m\le 2n-4,则求生成树的过程中至多有 n3n-3 条返祖边,每一条返祖边用并查集合并端点,最后必然剩下 3\ge 3 个未合并的集合(nn 个点至多合并 n3n-3 次),直接输出就好了。

    #include <bits/stdc++.h>
    using namespace std;
    
    namespace z {
    
    #define int long long
    const int N = 5e5 + 5;
    int fa[N], flag[N], vis[N];
    vector<int> p[N];
    int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); }
    void merge(int x, int y) { x = find(x), y = find(y); if(x != y) fa[x] = y; }
    void init(int n) { for(int i = 1; i <= n; i++) fa[i] = i, flag[i] = 0, vis[i] = 0, p[i].clear(); }
    void dfs(int u, int fa) {
        vis[u] = 1;
        for(auto v : p[u]) {
            if(v == fa) continue;
            if(vis[v]) merge(v, u);
            else dfs(v, u);
        }
    }
    void solve() {
        int n, m; cin >> n >> m;
        init(n);
        for(int i = 1; i <= m; i++) {
            int u, v; cin >> u >> v;
            p[u].push_back(v);
            p[v].push_back(u);
        }
        dfs(1, 0);
        for(int i = 2; i <= n; i++) if(!vis[i]) {
            vector<int> a1, a2;
            for(int j = 1; j <= n; j++) {
                if(vis[j]) a1.push_back(j);
                else a2.push_back(j);
            }
            if(a1.size() == 1) {
                cout << 1 << " " << a1[0] << '\n';
                cout << 1 << " " << a2[0] << '\n';
                cout << a2.size() - 1 << " ";
                for(auto j : a2) if(j != a2[0]) cout << j << ' ';
                cout << '\n';
            } else if(a2.size() == 1) {
                cout << 1 << " " << a1[0] << '\n';
                cout << 1 << " " << a2[0] << '\n';
                cout << a1.size() - 1 << " ";
                for(auto j : a1) if(j != a1[0]) cout << j << ' ';
            } else {
                cout << a1.size() << " ";
                for(auto j : a1) cout << j << ' ';
                cout << '\n';
                cout << 1 << " " << a2[0] << '\n';
                cout << a2.size() - 1 << " ";
                for(auto j : a2) if(j != a2[0]) cout << j << ' ';
            }
            return;
        }
        vector<int> ans;
        for(int i = 1; i <= n; i++) 
            if(find(i) == i) ans.push_back(i);
        vector<int> a[3];
        for(int i = 0; i <= 2; i++)
            for(int j = 1; j <= n; j++)
                if(find(j) == ans[i])
                    a[i].push_back(j), flag[j] = 1;
        for(int i = 1; i <= n; i++) 
            if(!flag[i]) a[0].push_back(i);
        for(int i = 0; i <= 2; i++) {
            cout << a[i].size() << ' ';
            for(auto j : a[i]) cout << j << ' ';
            cout << '\n';
        }
    }
    void main() {
    
        ios::sync_with_stdio(false);
        cin.tie(nullptr);cout.tie(nullptr);
        int T; cin >> T;
        while(T--) solve();
    
    }
    
    #undef int
    
    }
    
    
    int main()
    {
        z::main();
        return 0;
    }
    
    • 1

    信息

    ID
    11606
    时间
    1000ms
    内存
    512MiB
    难度
    5
    标签
    递交数
    0
    已通过
    0
    上传者