Cod sursa(job #3190468)

Utilizator Andrei137Neculae Andrei-Fabian Andrei137 Data 7 ianuarie 2024 17:17:13
Problema Taramul Nicaieri Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 4.12 kb
#include <iostream>
#include <climits>
#include <queue>
#include <vector>

void IO(const std::string& a_s)
{
    std::cin.tie(0)->sync_with_stdio(0);
    freopen((a_s + ".in").c_str(), "r", stdin);
    freopen((a_s + ".out").c_str(), "w", stdout);
}

template <typename T>
T read()
{
    T temp{};
    std::cin >> temp;
    return temp;
}

class Graph
{
    std::vector<std::vector<int>> m_edges{};
    std::vector<int> m_dad{};
    std::vector<bool> m_visited{};
    std::vector<std::vector<int>> m_capacity{};
    std::vector<std::vector<int>> m_flow{};
    int m_total;

    void init(int a_n, int a_src, int a_dst)
    {
        for (int i = 1; i <= a_n; ++i)
        {
            int x{ read<int>() };
            int y{ read<int>() };

            m_total += y;
            m_capacity[a_src][i] = x;
            m_capacity[a_n + i][a_dst] = y;
            m_edges[a_src].push_back(i);
            m_edges[i].push_back(a_src);
            m_edges[a_dst].push_back(a_n + i);
            m_edges[a_n + i].push_back(a_dst);
        }

        for (int i = 1; i <= a_n; ++i)
        {
            for (int j = 1; j <= a_n; ++j)
            {
                if (i != j)
                {
                    m_capacity[i][a_n + j] = 1;
                    m_edges[i].push_back(a_n + j);
                    m_edges[a_n + j].push_back(i);
                }
            }
        }
    }

    void bfs(int a_src, int a_dst)
    {
        m_visited.assign(a_dst + 1, false);

        std::queue<int> q{};
        q.push(a_src);
        m_visited[a_src] = true;

        m_dad[a_src] = 0;

        while (!q.empty())
        {
            int curr_node{ q.front() };
            q.pop();
            if (curr_node == a_dst)
            {
                continue;
            }

            for (int next_node : m_edges[curr_node])
            {
                if (!m_visited[next_node] && m_capacity[curr_node][next_node] != m_flow[curr_node][next_node])
                {
                    m_visited[next_node] = true;
                    m_dad[next_node] = curr_node;
                    q.push(next_node);
                }
            }
        }
    }

    void flux(int a_src, int a_dst)
    {
        while (true)
        {
            bfs(a_src, a_dst);

            if (!m_visited[a_dst])
            {
                break;
            }

            for (int next_node : m_edges[a_dst])
            {
                if (!m_visited[next_node] || m_capacity[next_node][a_dst] == m_flow[next_node][a_dst])
                {
                    continue;
                }

                m_dad[a_dst] = next_node;

                int min_flow{ INT_MAX };
                for (int curr_node = a_dst; curr_node != a_src; curr_node = m_dad[curr_node])
                {
                    min_flow = std::min(min_flow, m_capacity[m_dad[curr_node]][curr_node] - m_flow[m_dad[curr_node]][curr_node]);
                }

                if (min_flow == 0)
                {
                    break;
                }
                for (int curr_node = a_dst; curr_node != a_src; curr_node = m_dad[curr_node])
                {
                    m_flow[m_dad[curr_node]][curr_node] += min_flow;
                    m_flow[curr_node][m_dad[curr_node]] -= min_flow;
                }
            }
        }
    }

public:
    explicit Graph(int a_n) : m_edges(2 * a_n + 2), m_dad(2 * a_n + 2), m_capacity(2 * a_n + 2), m_flow(2 * a_n + 2), m_total(0)
    {
        for (auto& capacity : m_capacity)
        {
            capacity.resize(2 * a_n + 2);
        }
        for (auto& flow : m_flow)
        {
            flow.resize(2 * a_n + 2);
        }

        init(a_n, 0, 2 * a_n + 1);
    }

    void solve(int a_n)
    {
        flux(0, 2 * a_n + 1);

        std::cout << m_total << '\n';
        for (int i = 1; i <= a_n; ++i)
        {
            for (int j = 1; j <= a_n; ++j)
            {
                if (i != j && m_capacity[i][a_n + j] == m_flow[i][a_n + j])
                {
                    std::cout << i << ' ' << j << '\n';
                }
            }
        }
    }
};

int main()
{
    IO("harta");

    int n{ read<int>() };
    Graph g(n);
    g.solve(n);
    return 0;
}