Problem p01571 (C++) — buggy submission, verdict: Runtime Error

/*
 * -----------------------------------------------------------------
 * Copyright (c) 2015 crazyacking All rights reserved.
 * -----------------------------------------------------------------
 *       Author: crazyacking
 *       Verdict: Accepted
 *       Submission Date: 2015-11-08-20.49
 */
#include <algorithm>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
#define max(a, b) (a > b ? a : b)
using namespace std;
typedef long long(LL);
typedef unsigned long long(ULL);
const double eps(1e-8);

typedef pair<int, int> P;
struct edge {
  int to, cap, cost, rev;
};

int V;
vector<edge> G[50200];
int h[50200], dist[50200];
int prevv[50200], preve[50200];

void addEdge(int from, int to, int cap, int cost) {
  G[from].push_back((edge){to, cap, cost, G[to].size()});
  G[to].push_back((edge){from, 0, -cost, G[from].size() - 1});
}

int minCostFlow(int s, int t, int f) {
  int res = 0;
  fill(h, h + V, 0);
  while (f > 0) {
    priority_queue<P, vector<P>, greater<P>> pq;
    fill(dist, dist + V, 1000000000);
    dist[s] = 0;
    pq.push(P(0, s));
    while (!pq.empty()) {
      P p = pq.top();
      pq.pop();
      int v = p.second;
      if (dist[v] < p.first)
        continue;
      for (int i = 0; i < G[v].size(); i++) {
        edge &e = G[v][i];
        if (e.cap > 0 && dist[e.to] > dist[v] + e.cost + h[v] - h[e.to]) {
          dist[e.to] = dist[v] + e.cost + h[v] - h[e.to];
          prevv[e.to] = v;
          preve[e.to] = i;
          pq.push(P(dist[e.to], e.to));
        }
      }
    }

    if (dist[t] == 1000000000)
      return (-1);
    for (int v = 0; v < V; v++)
      h[v] += dist[v];

    int d = f;
    for (int v = t; v != s; v = prevv[v]) {
      d = min(d, G[prevv[v]][preve[v]].cap);
    }
    f -= d;
    res += d * h[t];
    for (int v = t; v != s; v = prevv[v]) {
      edge &e = G[prevv[v]][preve[v]];
      e.cap -= d;
      G[v][e.rev].cap += d;
    }
  }
  return (res);
}

int getDist(string s, string t) {
  int dp[32][32];
  for (int i = 0; i <= s.size(); i++)
    dp[i][0] = i;
  for (int i = 0; i <= t.size(); i++)
    dp[0][i] = i;

  for (int i = 1; i <= s.size(); i++)
    for (int j = 1; j <= t.size(); j++)
      dp[i][j] = min(min(dp[i - 1][j] + 1, dp[i][j - 1] + 1),
                     dp[i - 1][j - 1] + (s[i - 1] != t[j - 1]));
  return (dp[s.size()][t.size()]);
}

int main() {
  int N, M;
  vector<string> S, T;
  map<string, int> c;
  scanf("%d %d", &N, &M);
  getchar();

  for (int i = 0; i < N; i++) {
    char st[1024], *p;
    fgets(st, sizeof(st), stdin);
    p = strtok(st, " \\n");
    while (p != NULL) {
      S.push_back((string)p);
      if (c.count((string)p) == 0)
        c[(string)p] = 0;
      c[(string)p]++;
      p = strtok(NULL, " \\n");
    }
  }

  sort(S.begin(), S.end());
  S.erase(unique(S.begin(), S.end()), S.end());

  for (int i = 0; i < M; i++) {
    char st[1024];
    scanf("%s", st);
    T.push_back((string)st);
  }
  sort(T.begin(), T.end());
  T.erase(unique(T.begin(), T.end()), T.end());
  V = S.size() + T.size() + 2;
  for (int i = 0; i < S.size(); i++) {
    addEdge(0, i + 1, 1, 0);
    for (int j = 0; j < T.size(); j++) {
      addEdge(i + 1, S.size() + j + 1, 1, c[S[i]] * getDist(S[i], T[j]));
      if (!i)
        addEdge(S.size() + j + 1, S.size() + T.size() + 1, 1, 0);
    }
  }

  printf("%d\\n", minCostFlow(0, S.size() + T.size() + 1, S.size()));

  return (0);
}

Error: 0

Fixed submission:

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <vector>
using namespace std;
#define mod 1000000007
#define maxn 100005
#define INF 0x3f3f3f3f
int a[405][405];
int dp[25][25];
string s1[105];
string s2[405];
map<string, int> mp;
struct Edge {
  int from;
  int to;
  int cap;
  int flow;
  int cost;
};
struct MCMF {
  int n, m, s, t;
  vector<Edge> edges;
  vector<int> G[maxn];
  int inq[maxn]; // 是否在?列中
  int d[maxn];   // bellman-ford
  int p[maxn];   // 上一条弧
  int a[maxn];   // 可改?量
  void init(int n) {
    this->n = n;
    for (int i = 0; i < n; i++)
      G[i].clear();
    edges.clear();
  }
  void AddEdge(int from, int to, int cap, int cost) {
    edges.push_back((Edge){from, to, cap, 0, cost});
    edges.push_back((Edge){to, from, 0, 0, -cost});
    m = edges.size();
    G[from].push_back(m - 2);
    G[to].push_back(m - 1);
  }
  bool BellmanFord(int s, int t, int &flow, int &cost) {
    for (int i = 0; i < n; i++)
      d[i] = INF;
    memset(inq, 0, sizeof(inq));
    d[s] = 0;
    inq[s] = 1;
    p[s] = 0;
    a[s] = INF;
    queue<int> Q;
    Q.push(s);
    while (!Q.empty()) {
      int u = Q.front();
      Q.pop();
      inq[u] = 0;
      for (int i = 0; i < G[u].size(); i++) {
        Edge &e = edges[G[u][i]];
        if (e.cap > e.flow && d[e.to] > d[u] + e.cost) {
          d[e.to] = d[u] + e.cost;
          p[e.to] = G[u][i];
          a[e.to] = min(a[u], e.cap - e.flow);
          if (!inq[e.to]) {
            Q.push(e.to);
            inq[e.to] = 1;
          }
        }
      }
    }
    if (d[t] == INF)
      return false;
    flow += a[t];
    cost += d[t] * a[t];
    int u = t;
    while (u != s) {
      edges[p[u]].flow += a[t];
      edges[p[u] ^ 1].flow -= a[t];
      u = edges[p[u]].from;
    }
    return true;
  }

  int Mincost(int s, int t) {
    int flow = 0, cost = 0;
    while (BellmanFord(s, t, flow, cost))
      ;
    return cost;
  }
} g;
int main() {
  int n, m;
  scanf("%d%d", &n, &m);
  int tot = 0;
  getchar();
  for (int i = 0; i < n; i++) {
    string te;
    getline(cin, te);
    for (int j = 0; j < te.size(); j++) {
      if (te[j] == ' ') {
        mp[s1[tot]]++;
        tot++;
      } else
        s1[tot] += te[j];
    }
    mp[s1[tot]]++;
    tot++;
  }
  sort(s1, s1 + tot);
  tot = unique(s1, s1 + tot) - s1;
  g.init(tot + m + 3);
  for (int i = 0; i < m; i++)
    cin >> s2[i];
  for (int i = 0; i < tot; i++) {
    int leni = s1[i].size();
    for (int j = 0; j < m; j++) {
      int lenj = s2[j].size();
      for (int k = 0; k <= leni; k++)
        for (int p = 0; p <= lenj; p++)
          dp[k][p] = 40;
      dp[0][0] = 0;
      for (int k = 0; k <= leni; k++) {
        for (int p = 0; p <= lenj; p++) {
          if ((k < leni) && (p < lenj)) {
            if (s1[i][k] == s2[j][p])
              dp[k + 1][p + 1] = min(dp[k + 1][p + 1], dp[k][p]);
            else
              dp[k + 1][p + 1] = min(dp[k + 1][p + 1], dp[k][p] + 1);
          }
          if (k + 1 <= leni)
            dp[k + 1][p] = min(dp[k + 1][p], dp[k][p] + 1);
          if (p + 1 <= lenj)
            dp[k][p + 1] = min(dp[k][p + 1], dp[k][p] + 1);
        }
      }
      a[i][j] = dp[leni][lenj] * mp[s1[i]];
      g.AddEdge(i, j + tot, 1, dp[leni][lenj] * mp[s1[i]]);
    }
  }
  for (int i = 0; i < tot; i++)
    g.AddEdge(tot + m + 1, i, 1, 0);
  for (int i = 0; i < m; i++)
    g.AddEdge(i + tot, tot + m + 2, 1, 0);
  printf("%d\\n", g.Mincost(tot + m + 1, tot + m + 2));
}