#include <bits/stdc++.h>
using namespace std;
char ff[2005][2005];
int dist[2005][2005];
bool used[2005][2005] = {};
vector<int> par, ran;
void init(int n) {
  for (int i = 0; i < n; i++) {
    par.push_back(i);
    ran.push_back(0);
  }
}
int find(int x) {
  if (par[x] == x) {
    return x;
  } else {
    return par[x] = find(par[x]);
  }
}
void unite(int x, int y) {
  x = find(x);
  y = find(y);
  if (x == y) return;
  if (ran[x] < ran[y]) {
    par[x] = par[y];
  } else {
    par[y] = par[x];
    if (ran[x] == ran[y]) ran[x]++;
  }
}
bool same(int x, int y) { return find(x) == find(y); }
int main() {
  int h, w;
  scanf("%d %d", &h, &w);
  for (int i = 0; i < h; i++) {
    scanf("%s", &ff[i]);
  }
  queue<pair<int, pair<int, int> > > que;
  for (int i = 0; i < h; i++) {
    for (int j = 0; j < w; j++) {
      if (ff[i][j] == '#') {
        que.push(make_pair(0, make_pair(i, j)));
        dist[i][j] = 0;
      }
    }
  }
  vector<int> num;
  num.push_back(0);
  num.push_back(0);
  while (!que.empty()) {
    pair<int, pair<int, int> > p = que.front();
    que.pop();
    if (used[p.second.first][p.second.second]) continue;
    used[p.second.first][p.second.second] = true;
    if (num[0] < dist[p.second.first][p.second.second]) {
      swap(num[0], num[1]);
      num[0] = dist[p.second.first][p.second.second];
    } else if (num[1] < dist[p.second.first][p.second.second]) {
      num[1] = dist[p.second.first][p.second.second];
    }
    int dx[4] = {0, 1, 0, -1};
    int dy[4] = {-1, 0, 1, 0};
    char g[4] = {'>', '^', '<', 'v'};
    for (int i = 0; i < 4; i++) {
      if (0 <= p.second.first + dx[i] && p.second.first + dx[i] < h) {
        if (0 <= p.second.second + dy[i] && p.second.second + dy[i] < w) {
          if (ff[p.second.first + dx[i]][p.second.second + dy[i]] == g[i] &&
              !used[p.second.first + dx[i]][p.second.second + dy[i]]) {
            dist[p.second.first + dx[i]][p.second.second + dy[i]] = p.first + 1;
            que.push(make_pair(
                dist[p.second.first + dx[i]][p.second.second + dy[i]],
                make_pair(p.second.first + dx[i], p.second.second + dy[i])));
          }
        }
      }
    }
  }
  for (int i = 0; i < h; i++) {
    for (int j = 0; j < w; j++) {
      if (!used[i][j]) {
        puts("-1");
        return 0;
      }
    }
  }
  vector<pair<int, pair<int, int> > > gen;
  for (int i = 0; i < h; i++) {
    for (int j = 0; j < w; j++) {
      if (dist[i][j] == num[0] || dist[i][j] == num[1]) {
        gen.push_back(make_pair(dist[i][j], make_pair(i, j)));
      }
    }
  }
  init(gen.size());
  for (int t = 0; t < num[0]; t++) {
    map<pair<int, int>, vector<int> > ma;
    ma.clear();
    set<pair<int, int> > second;
    second.clear();
    for (int i = 0; i < gen.size(); i++) {
      if (ff[gen[i].second.first][gen[i].second.second] == '^') {
        gen[i].second.first--;
        if (ff[gen[i].second.first][gen[i].second.second] != '#' &&
            second.find(gen[i].second) != second.end()) {
          ma[gen[i].second].push_back(i);
        } else if (ff[gen[i].second.first][gen[i].second.second] != '#') {
          second.insert(gen[i].second);
          ma[gen[i].second].push_back(i);
        }
      } else if (ff[gen[i].second.first][gen[i].second.second] == 'v') {
        gen[i].second.first++;
        if (ff[gen[i].second.first][gen[i].second.second] != '#' &&
            second.find(gen[i].second) != second.end()) {
          ma[gen[i].second].push_back(i);
        } else if (ff[gen[i].second.first][gen[i].second.second] != '#') {
          second.insert(gen[i].second);
          ma[gen[i].second].push_back(i);
        }
      } else if (ff[gen[i].second.first][gen[i].second.second] == '<') {
        gen[i].second.second--;
        if (ff[gen[i].second.first][gen[i].second.second] != '#' &&
            second.find(gen[i].second) != second.end()) {
          ma[gen[i].second].push_back(i);
        } else if (ff[gen[i].second.first][gen[i].second.second] != '#') {
          second.insert(gen[i].second);
          ma[gen[i].second].push_back(i);
        }
      } else if (ff[gen[i].second.first][gen[i].second.second] == '>') {
        gen[i].second.second++;
        if (ff[gen[i].second.first][gen[i].second.second] != '#' &&
            second.find(gen[i].second) != second.end()) {
          ma[gen[i].second].push_back(i);
        } else if (ff[gen[i].second.first][gen[i].second.second] != '#') {
          second.insert(gen[i].second);
          ma[gen[i].second].push_back(i);
        }
      }
    }
    map<pair<int, int>, vector<int> >::iterator it;
    for (it = ma.begin(); it != ma.end(); ++it) {
      if (it->second.size() == 1) continue;
      for (int i = 1; i < (it->second).size(); i++) {
        unite((it->second)[i - 1], (it->second)[i]);
      }
    }
  }
  bool used[2005 * 2005] = {};
  int v1 = -1, v2 = -1;
  for (int i = 0; i < gen.size(); i++) {
    if (used[i]) continue;
    used[i] = true;
    int fa = -1;
    for (int j = i; j < gen.size(); j++) {
      if (same(i, j)) {
        fa = max(fa, gen[j].first);
        used[j] = true;
      }
    }
    if (v1 < fa) {
      swap(v1, v2);
      v1 = fa;
    } else if (v2 < fa)
      v2 = fa;
  }
  if (v2 == -1) v2 += v1;
  printf("%d\n", max(0, v1 + v2));
}
