Cod sursa(job #1809077)

Utilizator BrandonChris Luntraru Brandon Data 18 noiembrie 2016 17:19:25
Problema Cc Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.01 kb
#include <fstream>
#include <cstring>
#include <queue>
#include <assert.h>

using namespace std;

ifstream cin ("cc.in");
ofstream cout ("cc.out");

const int MaxN = 205, Inf = 0x3f3f3f3f;

class m_edg {
public:
    int node, cap, cost;

    m_edg (int _node = 0, int _cost = 0, int _cap = 1) {
        node = _node;
        cost = _cost;
        cap = _cap;
    }
};

m_edg G[10 * MaxN * MaxN];

class m_node {
public:
    int nd, cost;

    m_node (int _nd = 0, int _cost = 0) {
        nd = _nd;
        cost = _cost;
    }

    inline bool operator < (const m_node &other) const {
        return cost > other.cost;
    }
};

priority_queue <m_node> PrioQ;
int FirstNgb[MaxN], NextNgb[10 * MaxN * MaxN], father[MaxN], Dist[MaxN], used[MaxN], EdgFather[MaxN];
int n, EdgTop, Source = 0, Destination, Ans;

void AddEdge(int n1, int n2, int cost, int cap = 1) {
    ++EdgTop;
    G[EdgTop] = m_edg(n2, cost, cap);
    NextNgb[EdgTop] = FirstNgb[n1];
    FirstNgb[n1] = EdgTop;
}

inline void ClearPQ()  {
    while (PrioQ.size()) {
        PrioQ.pop();
    }
}

bool Dijkstra() {
    ClearPQ();
    memset(father, 0, sizeof father);
    memset(Dist, Inf, sizeof Dist);
    memset(used, 0, sizeof used);
    memset(EdgFather, 0, sizeof EdgFather);
    PrioQ.push(m_node(Source, 0));
    father[Source] = -1;
    Dist[Source] = 0;

    while (PrioQ.size()) {
        m_node node = PrioQ.top();
        PrioQ.pop();

        if (node.cost > Dist[node.nd]) {
            continue;
        }

        used[node.nd] = true;

        for (int NxtPtr = FirstNgb[node.nd]; NxtPtr; NxtPtr = NextNgb[NxtPtr]) {
            m_edg nxt = G[NxtPtr];
            if (node.cost + nxt.cost < Dist[nxt.node] and nxt.cap) {
                Dist[nxt.node] = node.cost + nxt.cost;
                father[nxt.node] = node.nd;
                EdgFather[nxt.node] = NxtPtr;
                PrioQ.push(m_node(nxt.node, Dist[nxt.node]));

                if (nxt.node == Destination) {
                    return true;
                }
            }
        }
    }

    return false;
}

int RevNode(int ptr) {
    return (ptr % 2 == 0) ? ptr - 1 : ptr + 1;
}

void FlowUpdate(int node = Destination) {
    while (node!=0) {
        assert(G[EdgFather[node]].cap+G[RevNode(EdgFather[node])].cap==1);

        G[EdgFather[node]].cap = 0;
        Ans+=G[EdgFather[node]].cost;

        G[RevNode(EdgFather[node])].cap = 1;
        node = father[node];
    }
}

int main() {
    cin >> n;
    Destination = 2 * n + 1;
    for (int i = 1; i <= n; ++i) {
        for (int j = n + 1; j <= 2 * n; ++j) {
            int a;
            cin >> a;
            AddEdge(i, j, a);
            AddEdge(j, i, -a, 0);
        }

        AddEdge(Source, i, 0);
        AddEdge(i, Source, 0, 0);

        AddEdge(n + i, Destination, 0);
        AddEdge(Destination, n + i, 0, 0);
    }

    while (Dijkstra()) {
        FlowUpdate();
    }
/*
    for (int i = 1; i <= EdgTop; i += 2) {
        if (G[i].cap == 0) {
            Ans += G[i].cost;
        }
    }
*/
    cout << Ans << '\n';
    assert(Ans>=n);
    return 0;
}