Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <vector>
- #include <queue>
- #include <list>
- namespace NFlow {
- typedef long long TFlow;
- typedef unsigned int TVertex;
- struct Edge {
- TVertex from, to;
- TFlow capacity, flow;
- };
- struct BadVertexId : public std::exception {};
- struct BadEdge : public std::exception {};
- struct SourceEqualsSink : public std::exception {};
- class Network {
- protected:
- std::vector<Edge> edges_;
- std::vector<int> lasts_, prev_;
- std::vector<int> inv_lasts_, inv_prev_;
- unsigned int vertexNumber_;
- TVertex source_, sink_;
- void addEdgeLocal_(TVertex from, TVertex to, TFlow capacity) {
- if (from < 0 || from >= vertexNumber_) {
- throw BadVertexId();
- }
- if (to < 0 || to >= vertexNumber_) {
- throw BadVertexId();
- }
- edges_.push_back({from, to, capacity, 0});
- prev_.push_back(lasts_[from]);
- lasts_[from] = (int) edges_.size() - 1;
- inv_prev_.push_back(inv_lasts_[to]);
- inv_lasts_[to] = (int) edges_.size() - 1;
- }
- void pushFlow_(int edge, TFlow flow) {
- edges_[edge].flow += flow;
- edges_[edge ^ 1].flow -= flow;
- }
- public:
- Network(int n, TVertex source, TVertex sink)
- : vertexNumber_(n),
- source_(source),
- sink_(sink),
- lasts_(n, -1),
- inv_lasts_(n, -1) {
- if (source_ >= vertexNumber_ || sink_ >= vertexNumber_) {
- throw BadVertexId();
- }
- if (source_ == sink_) {
- throw SourceEqualsSink();
- }
- }
- void addEdge(TVertex from, TVertex to, int capacity) {
- addEdgeLocal_(from, to, capacity);
- addEdgeLocal_(to, from, 0);
- }
- unsigned int getVertexNumber() const {
- return vertexNumber_;
- }
- TVertex getSource() const {
- return source_;
- }
- TVertex getSink() const {
- return sink_;
- }
- friend class EdgeIterator;
- class EdgeIterator {
- protected:
- friend class Network;
- int edgeId_;
- Network &network_;
- bool isForward_;
- EdgeIterator(int id, Network &network, bool isForward = true)
- : edgeId_(id),
- network_(network),
- isForward_(isForward) {}
- public:
- EdgeIterator &operator=(const EdgeIterator &a) {
- edgeId_ = a.edgeId_;
- network_ = a.network_;
- isForward_ = a.isForward_;
- return *this;
- }
- bool isValid() const {
- return edgeId_ >= 0;
- }
- EdgeIterator &goNext() {
- if (!isValid()) {
- throw BadEdge();
- }
- if (isForward_) {
- edgeId_ = network_.prev_[edgeId_];
- } else {
- edgeId_ = network_.inv_prev_[edgeId_];
- }
- return *this;
- }
- TVertex getFrom() const {
- return network_.edges_[edgeId_].from;
- }
- TVertex getTo() const {
- return network_.edges_[edgeId_].to;
- }
- TFlow getCapacity() const {
- return network_.edges_[edgeId_].capacity;
- }
- TFlow getFlow() const {
- return network_.edges_[edgeId_].flow;
- }
- TFlow getResudialCapacity() const {
- return getCapacity() - getFlow();
- }
- void pushFlow(TFlow flow) const {
- network_.pushFlow_(edgeId_, flow);
- }
- };
- EdgeIterator getListBegin(TVertex vertex, bool isForward = true) {
- return EdgeIterator((isForward ? lasts_[vertex] : inv_lasts_[vertex]), *this, isForward);
- }
- TFlow getFullFlow() {
- TFlow res = 0;
- for (auto it = getListBegin(getSource()); it.isValid(); it.goNext()) {
- res += it.getFlow();
- }
- return res;
- }
- };
- class Mincut {
- protected:
- Network *network_;
- std::vector<bool> inLeftPart_;
- void residualDfs_(TVertex vertex) {
- if (inLeftPart_[vertex]) return;
- inLeftPart_[vertex] = true;
- for (auto it = network_->getListBegin(vertex); it.isValid(); it.goNext()) {
- if (it.getResudialCapacity() > 0) {
- residualDfs_(it.getTo());
- }
- }
- }
- void build_() {
- inLeftPart_.assign(network_->getVertexNumber(), false);
- residualDfs_(network_->getSource());
- }
- public:
- explicit Mincut(Network *network) : network_(network) {
- unsigned int n = network_->getVertexNumber();
- inLeftPart_.assign(n, false);
- build_();
- }
- bool inLeft(TVertex vertex) {
- return inLeftPart_[vertex];
- }
- };
- class IFlow {
- protected:
- Network *network_;
- public:
- explicit IFlow(Network *network) : network_(network) {}
- explicit IFlow() : network_(nullptr) {}
- Network *getNetwork() {
- return network_;
- }
- void setNetwork(Network *network) {
- network_ = network;
- }
- virtual void run() = 0;
- virtual ~IFlow() = default;
- };
- class BlockingFlow : public IFlow {
- private:
- void createLayer_() {
- layer_.assign(network_->getVertexNumber(), -1);
- layer_[network_->getSource()] = 0;
- std::queue<TVertex> q;
- q.push(network_->getSource());
- while (!q.empty()) {
- TVertex v = q.front();
- q.pop();
- for (Network::EdgeIterator it = network_->getListBegin(v); it.isValid(); it.goNext()) {
- if (layer_[it.getTo()] == -1 && it.getResudialCapacity() > 0) {
- layer_[it.getTo()] = layer_[v] + 1;
- q.push(it.getTo());
- }
- }
- }
- }
- bool sinkIsReachable_() {
- return layer_[network_->getSink()] != -1;
- }
- protected:
- std::vector <int> layer_;
- virtual void findBlockingFlow() = 0;
- public:
- explicit BlockingFlow(Network *network) : IFlow(network), layer_(network_->getVertexNumber(), -1) {}
- explicit BlockingFlow() : IFlow(), layer_(0) {}
- void run() override {
- createLayer_();
- while (sinkIsReachable_()) {
- findBlockingFlow();
- createLayer_();
- }
- }
- };
- class MKM : public BlockingFlow {
- protected:
- static const TFlow INF_Flow = 1e18 + 7;
- std::vector<TFlow> sumIn_, sumOut_;
- std::vector<bool> erased_;
- TFlow getPotential_(TVertex vertex) {
- return std::min(sumIn_[vertex], sumOut_[vertex]);
- }
- void createPotential_() {
- unsigned int n = network_->getVertexNumber();
- sumIn_.assign(n, 0);
- sumOut_.assign(n, 0);
- for (TVertex v = 0; v < n; v++) {
- for (int isForward = 0; isForward < 2; isForward++) {
- for (Network::EdgeIterator it = network_->getListBegin(v, isForward); it.isValid(); it.goNext()) {
- if (layer_[(it.getFrom())] + 1 != layer_[(it.getTo())]) continue;
- if (isForward) {
- sumOut_[v] += it.getResudialCapacity();
- } else {
- sumIn_[v] += it.getResudialCapacity();
- }
- }
- }
- if (v == network_->getSource()) {
- sumIn_[v] = INF_Flow;
- }
- if (v == network_->getSink()) {
- sumOut_[v] = INF_Flow;
- }
- }
- }
- void updatePotential_(Network::EdgeIterator it) {
- if (layer_[it.getFrom()] + 1 == layer_[it.getTo()]) {
- sumOut_[it.getFrom()] -= it.getResudialCapacity();
- sumIn_[it.getTo()] -= it.getResudialCapacity();
- }
- }
- void tryToErase_() {
- bool found = true;
- while (found) {
- found = false;
- for (TVertex vertex = 0; vertex < network_->getVertexNumber(); vertex++) {
- if (erased_[vertex] || getPotential_(vertex) > 0) continue;
- erased_[vertex] = true;
- for (int isForward = 0; isForward < 2; isForward++) {
- for (auto it = network_->getListBegin(vertex, isForward); it.isValid(); it.goNext()) {
- updatePotential_(it);
- }
- }
- found = true;
- break;
- }
- }
- }
- void pushToward_(TVertex vertex, TFlow min_potential, bool isForward) {
- std::queue<std::pair<TVertex, TFlow> > q;
- q.push({vertex, min_potential});
- while (!q.empty()) {
- TVertex now = q.front().first;
- TFlow need = q.front().second;
- q.pop();
- for (auto it = network_->getListBegin(now, isForward); (need > 0 && it.isValid());
- updatePotential_(it), it.goNext()) {
- int layer_from = layer_[it.getFrom()];
- int layer_to = layer_[it.getTo()];
- if (layer_from + 1 != layer_to) continue;
- TVertex nxt = (isForward ? it.getTo() : it.getFrom());
- if (erased_[nxt]) continue;
- TFlow flow = std::min(need, it.getResudialCapacity());
- if (!flow) continue;
- q.push({nxt, flow});
- it.pushFlow(flow);
- sumOut_[it.getFrom()] -= flow;
- sumIn_[it.getTo()] -= flow;
- need -= flow;
- if (!need) break;
- }
- }
- }
- void findBlockingFlow() override {
- createPotential_();
- erased_.assign(network_->getVertexNumber(), false);
- while (true) {
- tryToErase_();
- if (erased_[network_->getSource()] || erased_[network_->getSink()]) break;
- TFlow min_potential = INF_Flow;
- TVertex vertex = network_->getSource();
- for (TVertex v = 0; v < network_->getVertexNumber(); v++) {
- TFlow now_potential = getPotential_(v);
- if (!erased_[v] && now_potential < min_potential) {
- min_potential = now_potential;
- vertex = v;
- }
- }
- pushToward_(vertex, min_potential, true);
- pushToward_(vertex, min_potential, false);
- }
- }
- public:
- explicit MKM(Network *network) : BlockingFlow(network) {
- unsigned int n = network_->getVertexNumber();
- sumIn_.resize(n, 0);
- sumOut_.resize(n, 0);
- erased_.resize(n, false);
- }
- explicit MKM() : BlockingFlow(), sumIn_(0), sumOut_(0), erased_(0) {}
- };
- class PushRelabel : public IFlow {
- protected:
- static const int INF = 1e9 + 7;
- std::vector<int> height_;
- std::vector<TFlow> excess_;
- void initialize_() {
- unsigned int n = network_->getVertexNumber();
- height_.assign(n, 0);
- excess_.assign(n, 0);
- TVertex source = network_->getSource();
- height_[source] = n;
- for (auto it = network_->getListBegin(source); it.isValid(); it.goNext()) {
- excess_[it.getTo()] += it.getResudialCapacity();
- it.pushFlow(it.getResudialCapacity());
- }
- }
- void push_(Network::EdgeIterator &it) {
- if (height_[it.getFrom()] != height_[it.getTo()] + 1) return;
- TFlow flow = std::min(excess_[it.getFrom()], it.getResudialCapacity());
- it.pushFlow(flow);
- excess_[it.getFrom()] -= flow;
- excess_[it.getTo()] += flow;
- }
- void relabel_(TVertex vertex) {
- int minh = INF;
- for (auto it = network_->getListBegin(vertex); it.isValid(); it.goNext()) {
- if (it.getResudialCapacity() == 0) continue;
- minh = std::min(minh, height_[it.getTo()]);
- }
- if (minh != INF) {
- height_[vertex] = minh + 1;
- }
- }
- virtual void pushExcess() = 0;
- public:
- explicit PushRelabel(Network *network) : IFlow(network) {
- unsigned int n = network->getVertexNumber();
- height_.resize(n), excess_.resize(n);
- }
- explicit PushRelabel() : IFlow(), height_(0), excess_(0) {}
- void run() override {
- initialize_();
- pushExcess();
- }
- };
- class PushRelabelToFront : public PushRelabel {
- protected:
- std::vector<Network::EdgeIterator> iterators_;
- std::list<TVertex> order_;
- void discharge_(TVertex vertex) {
- while (excess_[vertex]) {
- if (!iterators_[vertex].isValid()) {
- relabel_(vertex);
- iterators_[vertex] = network_->getListBegin(vertex);
- } else {
- int from = iterators_[vertex].getFrom(), to = iterators_[vertex].getTo();
- if (iterators_[vertex].getResudialCapacity() > 0 && height_[from] == height_[to] + 1) {
- push_(iterators_[vertex]);
- } else {
- iterators_[vertex].goNext();
- }
- }
- }
- }
- void pushExcess() override {
- for (TVertex vertex = 0; vertex < network_->getVertexNumber(); vertex++) {
- if (vertex != network_->getSource() && vertex != network_->getSink()) {
- order_.push_back(vertex);
- }
- iterators_.push_back(network_->getListBegin(vertex));
- }
- auto it = order_.begin();
- while (it != order_.end()) {
- TVertex vertex = *it;
- int old_h = height_[vertex];
- discharge_(vertex);
- if (height_[vertex] != old_h) {
- order_.erase(it);
- order_.push_front(vertex);
- it = order_.begin();
- }
- it++;
- }
- }
- public:
- explicit PushRelabelToFront(Network *network) : PushRelabel(network) {}
- explicit PushRelabelToFront() : PushRelabel() {}
- };
- }
- struct Data {
- int n;
- std::vector <int> a;
- std::vector <std::vector <int> > dependences;
- };
- Data readInput(std::istream &in) {
- int n;
- std::vector <int> a;
- std::vector <std::vector <int> > dependences;
- in >> n;
- a.resize(n);
- for (int i = 0; i < n; i++) {
- in >> a[i];
- }
- dependences.resize(n);
- for (int i = 0; i < n; i++) {
- int cnt;
- in >> cnt;
- for (int j = 0; j < cnt; j++) {
- int dep;
- in >> dep;
- dep--;
- dependences[i].push_back(dep);
- }
- }
- return {n, a, dependences};
- }
- NFlow::Network createNetwork(const Data &data) {
- const int INF = 1e9 + 7;
- int N = data.n + 2, source = N - 2, sink = N - 1;
- NFlow::Network network(N, source, sink);
- for (int i = 0; i < data.n; i++) {
- if (data.a[i] > 0) {
- network.addEdge(i, network.getSink(), data.a[i]);
- } else {
- network.addEdge(network.getSource(), i, -data.a[i]);
- }
- for (int v : data.dependences[i]) {
- network.addEdge(v, i, INF);
- }
- }
- return network;
- }
- long long solveWithFlows(NFlow::IFlow *flow, const Data &data) {
- auto network = createNetwork(data);
- flow->setNetwork(&network);
- flow->run();
- NFlow::Mincut mincut(flow->getNetwork());
- long long result = 0;
- for (int i = 0; i < data.n; i++) {
- if (!mincut.inLeft(i)) {
- result += data.a[i];
- }
- }
- return result;
- }
- void solve() {
- int n;
- std::vector <int> a;
- std::vector <std::vector <int> > dependences;
- long long result;
- Data data = readInput(std::cin);
- result = solveWithFlows(new NFlow::PushRelabelToFront(), data);
- std:: cout << result << "\n";
- }
- int main() {
- solve();
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement