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

#include <bits/stdc++.h>
using namespace std;
const int N = 100 + 10;
const int M = 10000 + 10;
struct edge {
  int u, v;
  double cost;
  edge() {}
  edge(int u, int v, double c) : u(u), v(v), cost(c) {}
} e[M];
int pre[N], hash1[N], vis[N];
double In[N];
double Directed_MST(int root, int n, int m) {
  double ret = 0;
  while (true) {
    for (int i = 0; i < n; i++)
      In[i] = INT_MAX;
    for (int i = 0; i < m; i++) // 找最小入?
    {
      int u = e[i].u;
      int v = e[i].v;
      if (e[i].cost < In[v] && u != v) {
        pre[v] = u;
        In[v] = e[i].cost;
      }
    }
    for (int i = 0; i < n; i++) {
      if (i == root)
        continue;
      if (In[i] == INT_MAX)
        return -1;
    }
    int cntnode = 0;
    memset(hash1, -1, sizeof(hash1));
    memset(vis, -1, sizeof(vis));
    In[root] = 0;
    for (int i = 0; i < n; i++) // 找?
    {
      ret += In[i];
      int v = i;
      while (vis[v] != i && hash1[v] == -1 && v != root) {
        vis[v] = i;
        v = pre[v];
      }
      if (v != root && hash1[v] == -1) {
        for (int u = pre[v]; u != v; u = pre[u])
          hash1[u] = cntnode;
        hash1[v] = cntnode++;
      }
    }
    if (cntnode == 0)
      break;
    for (int i = 0; i < n; i++)
      if (hash1[i] == -1)
        hash1[i] = cntnode++;
    for (int i = 0; i < m; i++) // 重??
    {
      int v = e[i].v;
      e[i].u = hash1[e[i].u];
      e[i].v = hash1[e[i].v];
      if (e[i].u != e[i].v)
        e[i].cost -= In[v];
    }
    n = cntnode;
    root = hash1[root];
  }
  return ret;
}
int n, m;
const int MAXV = 100 + 10;
double vc[MAXV][MAXV];
double A, B, C;
inline double calCost(double r) { return A - r * B + r * r * C; }
const double EPS = 1e-10;
inline int sgn(double x) { return x < -EPS ? -1 : x > EPS ? 1 : 0; }
int main() {
#ifdef ACM_TEST
  freopen("in.txt", "r", stdin);
//	freopen("in.txt", "w", stdout);
#endif
  scanf("%d%d", &m, &n);
  for (int i = 1; i <= n; ++i)
    for (int j = 0; j < m; ++j)
      scanf("%lf", &vc[i][j]);
  int tot = 0;
  for (int i = 1; i <= n; ++i) {
    double val = 0.0;
    for (int j = 0; j < m; ++j)
      val += vc[i][j] * vc[i][j];
    e[tot++] = edge(0, i, val);
  }
  for (int i = 1; i <= n; ++i)
    for (int j = 1; j <= n; ++j) {
      if (i == j)
        continue;
      A = 0, B = 0, C = 0;
      for (int k = 0; k < m; ++k) {
        A += vc[i][k] * vc[i][k];
        B += 2.0 * vc[i][k] * vc[j][k];
        C += vc[j][k] * vc[j][k];
      }
      double l = -1e8, r = 1e8, ll, rr;
      for (int k = 0; k < 100; ++k) {
        ll = (l + l + r) / 3.0;
        rr = (l + r + r) / 3.0;
        if (sgn(calCost(ll) - calCost(rr)) >= 0)
          l = ll;
        else
          r = rr;
      }
      e[tot++] = edge(j, i, calCost(l));
    }
  double ans = Directed_MST(0, n + 1, tot);
  printf("%.10f\\n", ans);
  return 0;
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;
const int N = 100 + 10;
const int M = 10000 + 10;
struct edge {
  int u, v;
  double cost;
  edge() {}
  edge(int u, int v, double c) : u(u), v(v), cost(c) {}
} e[M];
int pre[N], hash1[N], vis[N];
double In[N];
double Directed_MST(int root, int n, int m) {
  double ret = 0;
  while (true) {
    for (int i = 0; i < n; i++)
      In[i] = INT_MAX;
    for (int i = 0; i < m; i++) // 找最小入?
    {
      int u = e[i].u;
      int v = e[i].v;
      if (e[i].cost < In[v] && u != v) {
        pre[v] = u;
        In[v] = e[i].cost;
      }
    }
    for (int i = 0; i < n; i++) {
      if (i == root)
        continue;
      if (In[i] == INT_MAX)
        return -1;
    }
    int cntnode = 0;
    memset(hash1, -1, sizeof(hash1));
    memset(vis, -1, sizeof(vis));
    In[root] = 0;
    for (int i = 0; i < n; i++) // 找?
    {
      ret += In[i];
      int v = i;
      while (vis[v] != i && hash1[v] == -1 && v != root) {
        vis[v] = i;
        v = pre[v];
      }
      if (v != root && hash1[v] == -1) {
        for (int u = pre[v]; u != v; u = pre[u])
          hash1[u] = cntnode;
        hash1[v] = cntnode++;
      }
    }
    if (cntnode == 0)
      break;
    for (int i = 0; i < n; i++)
      if (hash1[i] == -1)
        hash1[i] = cntnode++;
    for (int i = 0; i < m; i++) // 重??
    {
      int v = e[i].v;
      e[i].u = hash1[e[i].u];
      e[i].v = hash1[e[i].v];
      if (e[i].u != e[i].v)
        e[i].cost -= In[v];
    }
    n = cntnode;
    root = hash1[root];
  }
  return ret;
}
int n, m;
const int MAXV = 100 + 10;
double vc[MAXV][MAXV];
inline double sqr(double x) { return x * x; }
double calCost(int a, int b, double r) {
  double res = 0.0;
  for (int i = 0; i < m; ++i)
    res += sqr(vc[a][i] - r * vc[b][i]);
  return res;
}
const double EPS = 1e-9;
inline int sgn(double x) { return x < -EPS ? -1 : x > EPS ? 1 : 0; }
int main() {
#ifdef ACM_TEST
  freopen("in.txt", "r", stdin);
//	freopen("in.txt", "w", stdout);
#endif
  scanf("%d%d", &m, &n);
  for (int i = 1; i <= n; ++i)
    for (int j = 0; j < m; ++j)
      scanf("%lf", &vc[i][j]);
  int tot = 0;
  for (int i = 1; i <= n; ++i) {
    e[tot++] = edge(0, i, calCost(i, 0, 0));
  }
  for (int i = 1; i <= n; ++i)
    for (int j = 1; j <= n; ++j) {
      if (i == j)
        continue;
      double l = -1e8, r = 1e8, ll, rr;
      while (sgn(r - l) > 0) {
        ll = (l + l + r) / 3.0;
        rr = (l + r + r) / 3.0;
        if (sgn(calCost(j, i, ll) - calCost(j, i, rr)) >= 0)
          l = ll;
        else
          r = rr;
      }
      e[tot++] = edge(i, j, calCost(j, i, l));
    }
  double ans = Directed_MST(0, n + 1, tot);
  printf("%.10f\\n", ans);
  return 0;
}