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

#include <algorithm>
#include <iostream>
#include <vector>

using namespace std;

typedef int ll;

const int INF = 1000000000;

struct Match {
  int n;
  vector<vector<int>> a;
  vector<int> memo;

  Match(int n) : n(n) {
    a.assign(n, vector<int>(n, 0));
    memo.assign((1 << n), -1);
  }

  void add(int i, int j, int w) {
    a[i][j] = w;
    a[j][i] = w;
  }

  int solve() { return solve(n, 0); }

  int solve(int n, int s) {
    if (s == ((1 << n) - 1)) {
      return 0;
    }
    if (memo[s] != -1) {
      return memo[s];
    }
    int best = INF;
    for (int k1 = 0; k1 < n; k1++) {
      if ((s & (1 << k1)) == 0) {
        for (int k2 = k1 + 1; k2 < n; k2++) {
          if ((s & (1 << k2)) == 0) {
            best = min(best, a[k1][k2] + solve(n, s | (1 << k1) | (1 << k2)));
          }
        }
      }
    }
    memo[s] = best;
    return best;
  }
};

struct FloydWarshall {
  int n;
  vector<vector<ll>> g;
  vector<vector<ll>> dists;

  FloydWarshall(int n) : n(n) { g.assign(n + 1, vector<ll>(n + 1, INF)); }

  void addEdge(int from, int to, ll w) {
    g[from][to] = min(g[from][to], w);
    g[to][from] = min(g[to][from], w);
  }

  bool solve() {
    dists.assign(n + 1, vector<ll>(n + 1, INF));
    for (int i = 0; i < n + 1; i++) {
      for (int j = 0; j < n + 1; j++) {
        dists[i][j] = g[i][j];
      }
      dists[i][i] = 0;
    }
    for (int k = 0; k < n; k++) {
      for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
          if (dists[i][k] < INF && dists[k][j] < INF &&
              dists[i][k] + dists[k][j] < dists[i][j]) {
            dists[i][j] = dists[i][k] + dists[k][j];
            if (i == j && dists[i][j] < 0) {
              return false;
            }
          }
        }
      }
    }
    return true;
  }
};

struct Edge {
  int from, to, w;

  Edge(int from = -1, int to = -1, int w = 0) : from(from), to(to), w(w) {}

  int other(int u) { return from == u ? to : from; }
};

struct Postman {
  int n;
  vector<vector<int>> g;
  vector<Edge> edges;
  int total = 0;

  Postman(int n) : n(n) { g.assign(n, vector<int>()); }

  void addEdge(int u, int v, int w) {
    total += w;
    edges.push_back(Edge(u, v, w));

    g[u].push_back(edges.size() - 1);
    g[v].push_back(edges.size() - 1);
  }

  int solve() {
    vector<int> mapping;
    for (int i = 0; i < n; i++) {
      if (g[i].size() % 2 != 0) {
        mapping.push_back(i);
      }
    }
    if (mapping.size() == 0) {
      return total;
    } else {
      FloydWarshall fw(n);
      for (int u = 0; u < n; u++) {
        for (int edgeId : g[u]) {
          Edge &edge = edges[edgeId];
          int v = edge.other(u);
          fw.addEdge(u, v, edge.w);
        }
      }
      fw.solve();
      int nsub = mapping.size();
      Match match(nsub);
      for (int i = 0; i < nsub; i++) {
        for (int j = i + 1; j < nsub; j++) {
          match.add(i, j, fw.dists[mapping[i]][mapping[j]]);
        }
      }
      return total + match.solve();
    }
  }
};

int main() {
  int n, e;
  cin >> n >> e;

  Postman postman(n);

  for (int i = 0; i < e; i++) {
    int from, to, w;
    cin >> from >> to >> w;
    postman.addEdge(from, to, w);
  }

  cout << postman.solve() << endl;

  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <iostream>
#include <vector>

using namespace std;

typedef int ll;

const int INF = 1000000000;

struct Match {
  int n;
  int best = INF;
  vector<vector<int>> a;

  Match(int n) : n(n) { a.assign(n, vector<int>(n, 0)); }

  void add(int i, int j, int w) {
    a[i][j] = w;
    a[j][i] = w;
  }

  int solve() {
    solve(n, 0, 0);
    return best;
  }

  void solve(int n, int s, int cost) {
    if (s == ((1 << n) - 1)) {
      best = min(best, cost);
      return;
    }
    for (int k1 = 0; k1 < n; k1++) {
      if ((s & (1 << k1)) == 0) {
        for (int k2 = k1 + 1; k2 < n; k2++) {
          if ((s & (1 << k2)) == 0) {
            solve(n, s | (1 << k1) | (1 << k2), cost + a[k1][k2]);
          }
        }
      }
    }
  }
};

struct FloydWarshall {
  int n;
  vector<vector<ll>> g;
  vector<vector<ll>> dists;

  FloydWarshall(int n) : n(n) { g.assign(n + 1, vector<ll>(n + 1, INF)); }

  void addEdge(int from, int to, ll w) {
    g[from][to] = min(g[from][to], w);
    g[to][from] = min(g[to][from], w);
  }

  bool solve() {
    dists.assign(n + 1, vector<ll>(n + 1, INF));
    for (int i = 0; i < n + 1; i++) {
      for (int j = 0; j < n + 1; j++) {
        dists[i][j] = g[i][j];
      }
      dists[i][i] = 0;
    }
    for (int k = 0; k < n; k++) {
      for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
          if (dists[i][k] < INF && dists[k][j] < INF &&
              dists[i][k] + dists[k][j] < dists[i][j]) {
            dists[i][j] = dists[i][k] + dists[k][j];
            if (i == j && dists[i][j] < 0) {
              return false;
            }
          }
        }
      }
    }
    return true;
  }
};

struct Edge {
  int from, to, w;

  Edge(int from = -1, int to = -1, int w = 0) : from(from), to(to), w(w) {}

  int other(int u) { return from == u ? to : from; }
};

struct Postman {
  int n;
  vector<vector<int>> g;
  vector<Edge> edges;
  int total = 0;

  Postman(int n) : n(n) { g.assign(n, vector<int>()); }

  void addEdge(int u, int v, int w) {
    total += w;
    edges.push_back(Edge(u, v, w));

    g[u].push_back(edges.size() - 1);
    g[v].push_back(edges.size() - 1);
  }

  int solve() {
    vector<int> mapping;
    for (int i = 0; i < n; i++) {
      if (g[i].size() % 2 != 0) {
        mapping.push_back(i);
      }
    }
    if (mapping.size() == 0) {
      return total;
    } else {
      FloydWarshall fw(n);
      for (int u = 0; u < n; u++) {
        for (int edgeId : g[u]) {
          Edge &edge = edges[edgeId];
          int v = edge.other(u);
          fw.addEdge(u, v, edge.w);
        }
      }
      fw.solve();

      int nsub = mapping.size();
      Match match(nsub);
      for (int i = 0; i < nsub; i++) {
        for (int j = i + 1; j < nsub; j++) {
          match.add(i, j, fw.dists[mapping[i]][mapping[j]]);
        }
      }
      return total + match.solve();
    }
  }
};

int main() {
  int n, e;
  cin >> n >> e;

  Postman postman(n);

  for (int i = 0; i < e; i++) {
    int from, to, w;
    cin >> from >> to >> w;
    postman.addEdge(from, to, w);
  }

  cout << postman.solve() << endl;

  return 0;
}