Submission #1213374

#TimeUsernameProblemLanguageResultExecution timeMemory
1213374borisAngelovConnecting Supertrees (IOI20_supertrees)C++20
100 / 100
141 ms22440 KiB
#include "supertrees.h"
#include <bits/stdc++.h>

using namespace std;

const int maxn = 1005;

struct DSU
{
    int par[maxn];
    int dep[maxn];
    vector<int> comps[maxn];

    void init(int n)
    {
        for (int i = 0; i < n; ++i)
        {
            comps[i].clear();
            comps[i].push_back(i);
            par[i] = i;
            dep[i] = 1;
        }
    }

    int root(int node)
    {
        if (node == par[node]) return node;
        return par[node] = root(par[node]);
    }

    void connect(int x, int y)
    {
        x = root(x);
        y = root(y);

        if (x == y) return;
        if (comps[x].size() < comps[y].size()) swap(x, y);

        par[y] = x;
        for (auto node : comps[y]) comps[x].push_back(node);
    }

    bool areConnected(int x, int y)
    {
        return root(x) == root(y);
    }
};

DSU dsu;
vector<vector<int>> answer;

void addEdge(int x, int y)
{
    answer[x][y] = answer[y][x] = true;
}

int construct(std::vector<std::vector<int>> p)
{
    int n = p.size();
    dsu.init(n);
    answer.resize(n);
    for (int i = 0; i < n; ++i)
    {
        answer[i].resize(n);
    }

    bool allOne = false;
    bool has2 = false;
    int has12 = 0;

    for (int i = 0; i < n; ++i)
    {
        for (int j = 0; j < n; ++j)
        {
            if (p[i][j] >= 3) return 0;
            if (p[i][j] == 1 && has12 <= 2) ++has12;
            if (p[i][j] == 2 && has12 <= 1) ++has12;

            allOne &= (p[i][j] == 1);
            has2 |= (p[i][j] == 2);
        }
    }

    if (allOne == true)
    {
        for (int i = 0; i < n - 1; ++i)
        {
            addEdge(i, i + 1);
        }

        build(answer);
        return 1;
    }

    for (int i = 0; i < n; ++i)
    {
        for (int j = i + 1; j < n; ++j)
        {
            if (p[i][j] > 0)
            {
                dsu.connect(i, j);
            }
        }
    }

    for (int i = 0; i < n; ++i)
    {
        for (int j = i + 1; j < n; ++j)
        {
            if (dsu.areConnected(i, j) == true && p[i][j] == 0) return 0;
            if (!dsu.areConnected(i, j) && p[i][j] > 0) return 0;
        }
    }

    if (has12 == 3)
    {
        DSU dsu1;
        dsu1.init(n);

        for (int i = 0; i < n; ++i)
        {
            for (int j = i + 1; j < n; ++j)
            {
                if (p[i][j] == 1)
                {
                    dsu1.connect(i, j);
                }
            }
        }

        vector<vector<int>> allComps;
        vector<int> whichComp(n, -1);
        vector<int> compRoot(n, -1);
        int compCnt = 0;

        for (int i = 0; i < n; ++i)
        {
            int root = dsu1.root(i);
            if (whichComp[root] >= 0) continue;

            vector<int> comp = dsu1.comps[root];
            for (auto node : comp)
            {
                whichComp[node] = compCnt;
            }
            for (int j = 0; j < comp.size() - 1; ++j)
            {
                addEdge(comp[j], comp[j + 1]);
            }

            allComps.push_back(comp);
            compRoot[compCnt] = comp[0];
            ++compCnt;
        }

        DSU dsu2;
        dsu2.init(n);

        for (int i = 0; i < n; ++i)
        {
            for (int j = i + 1; j < n; ++j)
            {
                if (p[i][j] == 2)
                {
                    dsu2.connect(whichComp[i], whichComp[j]);
                }
            }
        }

        vector<bool> seen(n, false);

        for (int i = 0; i < n; ++i)
        {
            int root = dsu2.root(i);
            if (seen[root] == true) continue;
            seen[root] = true;

            vector<int> roots = dsu2.comps[root];
            if (roots.size() <= 1) continue;
            if (roots.size() == 2) return 0;

            for (int j = 0; j < roots.size(); ++j)
            {
                int curr = roots[j];
                int nxt = roots[(j + 1) % int(roots.size())];
                addEdge(compRoot[curr], compRoot[nxt]);
            }
        }

        build(answer);
        return 1;
    }

    vector<bool> seen(n, false);

    for (int i = 0; i < n; ++i)
    {
        int root = dsu.root(i);

        if (seen[root] == true) continue;
        seen[root] = true;

        if (dsu.comps[root].size() <= 1) continue;

        vector<int> nodes = dsu.comps[root];

        for (int j = 0; j < nodes.size() - 1; ++j)
        {
            addEdge(nodes[j], nodes[j + 1]);
        }

        if (has2 == true)
        {
            if (nodes.size() == 2) return 0;
            addEdge(nodes[0], nodes[nodes.size() - 1]);
        }
    }

    build(answer);
    return 1;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...