#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> l_l;
typedef pair<int, int> i_i;
template<class T>
inline bool chmax(T &a, T b) {
    if(a < b) {
        a = b;
        return true;
    }
    return false;
}

template<class T>
inline bool chmin(T &a, T b) {
    if(a > b) {
        a = b;
        return true;
    }
    return false;
}

const long double EPS = 1e-10;
const long long INF = 1e18;
const long double PI = acos(-1.0L);
typedef vector<vector<int>> UnWeightedGraph;
template< typename G >
struct LowLink {
  const G &g;
  vector< int > used, ord, low;
  vector< int > articulation;
  vector< pair< int, int > > bridge;
 
  LowLink(const G &g) : g(g) {}
 
  int dfs(int idx, int k, int par) {
    used[idx] = true;
    ord[idx] = k++;
    low[idx] = ord[idx];
    bool is_articulation = false;
    int cnt = 0;
    for(auto &to : g[idx]) {
      if(!used[to]) {
        ++cnt;
        k = dfs(to, k, idx);
        low[idx] = min(low[idx], low[to]);
        is_articulation |= ~par && low[to] >= ord[idx];
        if(ord[idx] < low[to]) bridge.emplace_back(minmax(idx, (int) to));
      } else if(to != par) {
        low[idx] = min(low[idx], ord[to]);
      }
    }
    is_articulation |= par == -1 && cnt > 1;
    if(is_articulation) articulation.push_back(idx);
    return k;
  }
 
  virtual void build() {
    used.assign(g.size(), 0);
    ord.assign(g.size(), 0);
    low.assign(g.size(), 0);
    int k = 0;
    for(int i = 0; i < g.size(); i++) {
      if(!used[i]) k = dfs(i, k, -1);
    }
  }
};
template< typename G >
struct TwoEdgeConnectedComponents : LowLink< G > {
  using LL = LowLink< G >;
  vector< int > comp;
 
  TwoEdgeConnectedComponents(const G &g) : LL(g) {}
 
  int operator[](const int &k) {
    return comp[k];
  }
 
  void dfs(int idx, int par, int &k) {
    if(~par && this->ord[par] >= this->low[idx]) comp[idx] = comp[par];
    else comp[idx] = k++;
    for(auto &to : this->g[idx]) {
      if(comp[to] == -1) dfs(to, idx, k);
    }
  }
 
  void build(UnWeightedGraph &t) {
    LL::build();
    comp.assign(this->g.size(), -1);
    int k = 0;
    for(int i = 0; i < comp.size(); i++) {
      if(comp[i] == -1) dfs(i, -1, k);
    }
    t.resize(k);
    for(auto &e : this->bridge) {
      int x = comp[e.first], y = comp[e.second];
      t[x].push_back(y);
      t[y].push_back(x);
    }
  }
};
//const ll mod = 1000000007;
map<string, int> inv;
vector<ll> sz;
ll dp[101][101][101];
ll field[101][101];
int n;
UnWeightedGraph g, t;

void dfs(int now, int from) {
    //cerr << "dfs: " << now << endl;
    for(int i = 0; i <= 100; i++) {
        for(int j = 0; j <= 100; j++) {
            dp[now][i][j] = -INF;
        }
    }
    dp[now][0][0] = 0;
    for(auto to : t[now]) {
        if(to == from) continue;
        dfs(to, now);
        for(int i = 0; i <= 100; i++) {
            for(int j = 0; j <= 100; j++) {
                field[i][j] = -INF;
            }
        }
        for(int delta = 0; delta <= 100; delta++) {
            ll maxi = -INF;
            for(int i = 0; i <= 100; i++) {
                chmax(maxi, dp[to][delta][i]);
            }
            if(maxi < 0) continue;
            for(int i = 0; i + delta <= 100; i++) {
                for(int j = 0; j <= 100; j++) {
                    chmax(field[i+delta][j], dp[now][i][j]+maxi);
                }
            }
        }
        for(int delta = 0; delta <= 100; delta++) {
            ll maxi = -INF;
            for(int i = 0; i <= 100; i++) {
                chmax(maxi, dp[to][i][delta]);
            }
            if(maxi < 0) continue;
            for(int i = 0; i + delta <= 100; i++) {
                for(int j = 0; j <= 100; j++) {
                    chmax(field[j][i+delta], dp[now][j][i]+maxi);
                }
            }
        }
        swap(dp[now], field);
    }
    for(ll i = 0; i <= 100; i++) {
        for(ll j = 0; j <= 100; j++) {
            dp[now][i][j] += i * j + sz[now]*i + sz[now]*j;
        }
    }
    for(int i = 100; i >= 0; i--) {
        for(int j = 100; j >= 0; j--) {
            if(i >= sz[now] and j >= sz[now]) {
                dp[now][i][j] = dp[now][i-sz[now]][j-sz[now]];
            } else {
                dp[now][i][j] = -INF;
            }
        }
    }
    /*
    for(int i = 0; i <= 100; i++) {
        for(int j = 0; j <= 100; j++) {
            if(dp[now][i][j] < 0) continue;
            cerr << now << " " << i << " " << j << " " << dp[now][i][j] << endl;
        }
    }
    */
}

int main() {
    int N, M;
    cin >> N >> M;
    g.resize(N);
    for(int i = 0; i < N; i++) {
        string s;
        cin >> s;
        inv[s] = i;
    }
    for(int m = 0; m < M; m++) {
        string a, b;
        cin >> a >> b;
        int A = inv[a];
        int B = inv[b];
        g[A].push_back(B);
        g[B].push_back(A);
    }
    TwoEdgeConnectedComponents<UnWeightedGraph> TECC(g);
    TECC.build(t);
    n = t.size();
    sz.resize(n);
    for(int i = 0; i < N; i++) {
        sz[TECC[i]]++;
    }
    ll base = 0;
    for(int i = 0; i < t.size(); i++) {
        base += sz[i] * sz[i];
        /*
        cerr << "--" << i << "--" << sz[i] << "---" << endl;
        for(auto to : t[i]) cerr << to << " ";
        cerr << endl;
        */
    }
    //cerr << base << endl;
    dfs(0, -1);
    ll ans = base;
    for(int i = 0; i <= 100; i++) {
        for(int j = 0; j <= 100; j++) {
            if(dp[0][i][j] < 0) continue;
            //cerr << i << " " << j << " " << dp[0][i][j] << endl;
            chmax(ans, base + dp[0][i][j]);
        }
    }
    cout << ans << endl;
    return 0;
}


Measured memory_bytes: 11280