Problem p00269 (C++) — buggy submission, verdict: Time Limit Exceeded

// ???????????????
#include <functional>
#include <map>
#include <queue>
#include <tuple>
#include <vector>
// ?????????
const int NIL = -1;
const double INF = 1e9;
class MinimumCostFlow {
private:
  struct Edge {
    int from, to;
    double weight, capacity;
    Edge() {}
    Edge(int f, int t, double w, double c)
        : from(f), to(t), weight(w), capacity(c) {}
    bool operator<(const Edge &e) const { return from < e.from; }
  };

public:
  void insert(int f, int t, double w, double c);
  double PrimalDual(int source, int sink, int n) const;

private:
  std::map<int, std::vector<Edge>> edge_;
};
// ????????????
void MinimumCostFlow::insert(int f, int t, double w, double c) {
  edge_[f].emplace_back(f, t, w, c);
  edge_[t].emplace_back(t, f, -w, 0);
}
// ????°??????¨??? O(????????? * (E + V log V))
double MinimumCostFlow::PrimalDual(int source, int sink, int n) const {
  std::map<int, std::map<int, double>> flow;
  std::map<int, double> distance;
  double result = 0;
  while (true) {
    // source ?????? Dijkstra
    std::map<int, double> difference;
    std::map<int, Edge> via;
    typedef std::tuple<double, Edge> Node;
    std::priority_queue<Node, std::vector<Node>, std::greater<Node>> q;
    q.emplace(0, Edge(source, source, 0, 0));
    while (!q.empty()) {
      double dif;
      Edge edge;
      std::tie(dif, edge) = q.top();
      q.pop();
      int prev = edge.from;
      int current = edge.to;
      if (difference.count(current))
        continue;
      difference[current] = dif;
      via[current] = edge;
      if (edge_.count(current))
        for (const auto &e : edge_.at(current)) {
          double residue = e.capacity - flow[e.from][e.to];
          double d = e.weight + distance[e.from] - distance[e.to];
          if (residue > 0)
            q.emplace(dif + d, e);
        }
    }
    // ???????????¢?????´??°
    for (auto d : difference)
      distance[d.first] += d.second;
    // sink ?????§?????????????????¨??????????????°??????
    if (!via.count(sink))
      break;
    // ?????????????????????????????????
    double add = INF;
    for (int v = sink; v != via[v].from; v = via[v].from)
      add = std::min(add, via[v].capacity - flow[via[v].from][via[v].to]);
    for (int v = sink; v != via[v].from; v = via[v].from) {
      flow[via[v].from][via[v].to] += add;
      flow[via[v].to][via[v].from] -= add;
      result += add * via[v].weight;
    }
    n -= add;
    if (n == 0)
      return result;
  }
  return -1;
}

#include <bits/stdc++.h>
using namespace std;

vector<int> memo(9);
int pow3(int n) {
  return memo[n] ? memo[n] : (memo[n] = (n < 1 ? 1 : 3 * pow3(n - 1)));
}

int main() {
  int D, K, L;
  while (cin >> D >> K >> L, D | K | L) {
    vector<vector<int>> c(D, vector<int>(K));
    for (auto &i : c)
      for (auto &j : i)
        cin >> j;
    int M, N, P;
    cin >> M >> N >> P;
    vector<vector<int>> r(M, vector<int>(K));
    for (auto &i : r)
      for (auto &j : i)
        cin >> j;
    vector<vector<int>> t(P, vector<int>(K));
    for (auto &i : t)
      for (auto &j : i)
        cin >> j;

    const int INF = 1e9;
    vector<vector<vector<int>>> dp(
        D + 1, vector<vector<int>>(pow3(K), vector<int>(L + 1, INF)));
    dp[0][0][0] = 0;
    for (int day = 0; day < D; ++day)
      for (int ternary = 0; ternary < pow3(K); ++ternary)
        for (int bought = 0; bought <= L; ++bought) {
          dp[day + 1][ternary][0] =
              min(dp[day + 1][ternary][0], dp[day][ternary][bought]);
          if (bought == L)
            continue;
          for (int part = 0; part < K; ++part) {
            int owned = (ternary / pow3(part)) % 3;
            if (2 <= owned)
              continue;
            dp[day][ternary + pow3(part)][bought + 1] =
                min(dp[day][ternary + pow3(part)][bought + 1],
                    dp[day][ternary][bought] + c[day][part]);
          }
        }

    //     for(int ternary = 0; ternary < pow3(K); ++ternary) for(int bought =
    //     0; bought <= L; ++bought) {
    //       for(int i = 0; i < K; ++i) cout<<((ternary / pow3(i)) % 3);
    //       cout<<": "<<dp[2][ternary][bought]<<endl;
    //     }

    MinimumCostFlow graph;
    int no_bag = P + M;
    int source = P + M + 1;
    int sink = P + M + 2;
    graph.insert(source, no_bag, 0, INF);
    for (int i = 0; i < P; ++i)
      graph.insert(source, i, 0, 1);
    for (int j = 0; j < M; ++j)
      graph.insert(P + j, sink, 0, 1);
    for (int j = 0; j < M; ++j) {
      int need = 0;
      for (int part = 0; part < K; ++part)
        need += pow3(part) * r[j][part];
      if (dp[D][need][0] != INF)
        graph.insert(no_bag, P + j, dp[D][need][0], 1);
      for (int i = 0; i < P; ++i) {
        int remain = need;
        for (int part = 0; part < K; ++part) {
          if (r[j][part] - t[i][part] < 0) {
            remain = -1;
            break;
          }
          remain -= pow3(part) * t[i][part];
        }
        if (~remain)
          if (dp[D][remain][0] != INF)
            graph.insert(i, P + j, dp[D][remain][0], 1);
      }
    }

    cout << graph.PrimalDual(source, sink, N) << endl;
  }
}

Error: TLE

Fixed submission:

#include <functional>
#include <map>
#include <queue>
#include <tuple>
#include <vector>
// ?????????
const int NIL = -1;
const double INF = 1e9;
class MinimumCostFlow {
private:
  struct Edge {
    int from, to;
    double weight, capacity;
    Edge() {}
    Edge(int f, int t, double w, double c)
        : from(f), to(t), weight(w), capacity(c) {}
    bool operator<(const Edge &e) const { return from < e.from; }
  };

public:
  void insert(int f, int t, double w, double c);
  double PrimalDual(int source, int sink, int n) const;

private:
  std::map<int, std::vector<Edge>> edge_;
};
// ????????????
void MinimumCostFlow::insert(int f, int t, double w, double c) {
  edge_[f].emplace_back(f, t, w, c);
  edge_[t].emplace_back(t, f, -w, 0);
}
// ????°??????¨??? O(????????? * (E + V log V))
double MinimumCostFlow::PrimalDual(int source, int sink, int n) const {
  std::map<int, std::map<int, double>> flow;
  std::map<int, double> distance;
  double result = 0;
  while (true) {
    // source ?????? Dijkstra
    std::map<int, double> difference;
    std::map<int, Edge> via;
    typedef std::tuple<double, Edge> Node;
    std::priority_queue<Node, std::vector<Node>, std::greater<Node>> q;
    q.emplace(0, Edge(source, source, 0, 0));
    while (!q.empty()) {
      double dif;
      Edge edge;
      std::tie(dif, edge) = q.top();
      q.pop();
      int prev = edge.from;
      int current = edge.to;
      if (difference.count(current))
        continue;
      difference[current] = dif;
      via[current] = edge;
      if (edge_.count(current))
        for (const auto &e : edge_.at(current)) {
          double residue = e.capacity - flow[e.from][e.to];
          double d = e.weight + distance[e.from] - distance[e.to];
          if (residue > 0)
            q.emplace(dif + d, e);
        }
    }
    // ???????????¢?????´??°
    for (auto d : difference)
      distance[d.first] += d.second;
    // sink ?????§?????????????????¨??????????????°??????
    if (!via.count(sink))
      break;
    // ?????????????????????????????????
    double add = INF;
    for (int v = sink; v != via[v].from; v = via[v].from)
      add = std::min(add, via[v].capacity - flow[via[v].from][via[v].to]);
    for (int v = sink; v != via[v].from; v = via[v].from) {
      flow[via[v].from][via[v].to] += add;
      flow[via[v].to][via[v].from] -= add;
      result += add * via[v].weight;
    }
    n -= add;
    if (n == 0)
      return result;
  }
  return -1;
}

#include <bits/stdc++.h>
using namespace std;

int get_part(int purchased, int part) {
  return (purchased >> part >> part) & 3;
}
int set_part(int purchased, int part, int n) {
  if ((purchased >> part >> part) & 1)
    purchased ^= (1 << part << part);
  if ((purchased >> part >> part) & 2)
    purchased ^= (1 << part << part << 1);
  return purchased | (n << part << part);
}

int main() {
  int D, K, L;
  while (cin >> D >> K >> L, D | K | L) {
    vector<vector<int>> c(D, vector<int>(K));
    for (auto &i : c)
      for (auto &j : i)
        cin >> j;
    int M, N, P;
    cin >> M >> N >> P;
    vector<vector<int>> r(M, vector<int>(K));
    for (auto &i : r)
      for (auto &j : i)
        cin >> j;
    vector<vector<int>> t(P, vector<int>(K));
    for (auto &i : t)
      for (auto &j : i)
        cin >> j;

    const int INF = 1000000000;
    vector<vector<vector<int>>> dp(
        D + 1, vector<vector<int>>(1 << (2 * K), vector<int>(L + 1, INF)));
    dp[0][0][0] = 0;
    for (int day = 1; day <= D; ++day) {
      for (int purchased = 0; purchased < (1 << (2 * K)); ++purchased) {
        for (int number = 0; number <= L; ++number) {
          dp[day][purchased][0] =
              min(dp[day][purchased][0], dp[day - 1][purchased][number]);
        }
      }
      for (int purchased = 0; purchased < (1 << (2 * K)); ++purchased) {
        for (int number = 0; number < L; ++number) {
          for (int part = 0; part < K; ++part) {
            int g = get_part(purchased, part);
            if (g >= 2)
              continue;
            int p = set_part(purchased, part, g + 1);
            int n = number + 1;
            dp[day][p][n] = min(dp[day][p][n],
                                dp[day][purchased][number] + c[day - 1][part]);
            if (g != 0)
              continue;
            if (number == L - 1)
              continue;
            p = set_part(purchased, part, g + 2);
            n = number + 2;
            dp[day][p][n] = min(dp[day][p][n], dp[day][purchased][number] +
                                                   2 * c[day - 1][part]);
          }
        }
      }
    }

    MinimumCostFlow graph;
    int none = P + M;
    int source = P + M + 1;
    int sink = P + M + 2;
    graph.insert(source, none, 0, INF);
    for (int i = 0; i < P; ++i)
      graph.insert(source, i, 0, 1);
    for (int j = 0; j < M; ++j)
      graph.insert(P + j, sink, 0, 1);
    for (int j = 0; j < M; ++j) {
      int need = 0;
      for (int k = 0; k < K; ++k)
        need = set_part(need, k, r[j][k]);
      int cost = INF;
      for (int number = 0; number <= L; ++number)
        cost = min(cost, dp[D][need][number]);
      if (cost != INF)
        graph.insert(none, P + j, cost, 1);
      for (int i = 0; i < P; ++i) {
        int remain = need;
        bool ok = true;
        for (int k = 0; k < K; ++k) {
          int g = get_part(need, k) - t[i][k];
          if (g < 0) {
            ok = false;
            break;
          }
          remain = set_part(remain, k, g);
        }
        if (!ok)
          continue;
        cost = INF;
        for (int number = 0; number <= L; ++number)
          cost = min(cost, dp[D][remain][number]);
        if (cost == INF)
          continue;
        graph.insert(i, P + j, cost, 1);
      }
    }

    cout << graph.PrimalDual(source, sink, N) << endl;
    //     for(int j = 0; j < (1 << (2 * K)); ++j) {
    //       bool ok = true;
    //       for(int k = 0; k <= L; ++k) if(get_part(j, k) >= 3) ok = false;
    //       if(!ok) continue;
    //       for(int k = 0; k <= L; ++k) {
    //         cout<<" "<<bitset<4>(j)<<":"<<dp[D][j][k]<<endl;
    //       }
    //     }
  }
}