Problem: The 15th month of 2119. A spellbook was written by the court magician Sengemon Lugene. This magic book "In Magiray" was an innovative book in that it systematized "double magic", which is deeply related to the basis of the magic law of this world, as a technique that anyone can learn. First, let's take a look at a summary of the contents of this book.

【element】
Every object in the world is composed of tiny elements such as "spring", "wind", "feather", "flower", "sand", "light", and so on. There are many types of elements, and by signing a contract with an element, humans can activate double magic using the type of element with which they have a contract.

[Double magic]
Double magic, as the name implies, is magic that superimposes two elements and releases them. The main element is called the "main attribute" and the other is called the "sub-attribute". For example, if the primary attribute is "light" and the secondary attribute is "flower", the double magic is written as (light, flower). (Light, flower) and (flower, light) are different double magics. Moreover, the primary attribute and the sub-attribute may be the same.

【keyword】
Each element can have a one-to-one correspondence with a short "keyword" such as "spring → huda", "wind → loar", "feather → sheza", and "flower → leide". A keyword is an epoch-making concept that makes it possible to easily activate double magic simply by chanting a few consecutive keyword strings by symbolizing the nature of the element in short words.

【incantation】
A spell is a sequence of one or more keywords, such as "huda, leide, loar, sheza". By casting the spell intended by the caster, you can activate the corresponding double spell. Specifically, double magic is activated with the element corresponding to the first keyword of the spell as the main attribute and the element corresponding to the last keyword as the sub attribute. In the example of the spell I mentioned earlier, the double magic that is activated is (fountain, feather). If the spell consists of only one keyword, both the primary attribute and the sub-attribute are the elements corresponding to that keyword.

[Compatibility between elements]
I have already mentioned that the spell "huda, leide, loar, sheza" activates the double magic of (fountain, feather). However, at first glance, if you want to use (fountain, feather), it seems that you can just use "huda / sheza" without having to cast a long spell. But in reality, that is not possible. This is because "huda" and "sheza" are not compatible, and if you cast a spell in which these two are next to each other, a repulsive action will occur and the elements will cancel each other out. On the other hand, "fountain (huda)" and "flower (leide)", "flower (leide)" and "wind (loar)", "wind (loar)" and "feather (sheza)" are all good. Because of their compatibility, spells such as "huda, leide, loar, sheza" and "loar, leide, huda" do not offset elements.

[Spell logic]
Those who want to use double magic should define in advance which keyword is the "upper word" and which keyword is the "lower word" for each pair of compatible elements. There must be. When A is defined as the upper word and B is defined as the lower word for the keywords "A" and "B" of two compatible elements, it is written as A> B. When A> B, A cannot be placed immediately after B in a spell. In other words, if "A1, A2, A3 ... Ak" is the correct spell, it must be A1> A2, A2> A3, ..., Ak-1> Ak. By the way, even if A> B and B> C, it does not have to be A> C.

In this way, each surgeon defines the upper and lower words to his or her own taste, which is called "construction of spell logic". This is a device to clarify the flow of elements and increase the success probability of the target double magic by intentionally restricting the syntax of the spell. However, the price is that building spell logic can result in double spells that can't be cast no matter how you cast the spell (although you can use it no matter what spell logic you build. It has been proven that there is no double magic that cannot be done). Given these circumstances, what kind of spell logic to build is a thorny issue that has plagued many magicians both now and in the past.

Uto, an apprentice magician boy living in a small town, has signed contracts with all the elements and is about to perform a ritual to build his spell logic tomorrow. Ute simply thought that spell logic that could cast as many types of double magic as possible was good spell logic.

As a super-first-class electrician (super programmer in modern Japan), how many types of double magic can you use if you can successfully build spell logic from your friend Ute? I was consulted to know. This is a difficult problem that humans around the world have challenged, but no one could solve. If you can solve it, your name will be handed down all over the world in the future.



Input

N M
s1
s2
..
..
..
sN
p1 q1 p2 q2.
..
..
pM M


On the first line of input, the integer N and the integer M are written separated by blanks. This means that there are a total of N types of elements and a total of M pairs of compatible elements.

One character string is written in the following N lines. The character string si written on the 1 + i line indicates that the keyword corresponding to the i-th element is si.

On the following M line, two strings are written separated by blanks. The character strings pi and qi written on the 1 + N + i lines indicate that the element corresponding to the keyword pi and the pair of elements corresponding to the keyword qi are compatible. Conversely, pairs of elements that do not appear here are not compatible.

These data satisfy the following conditions.

* 2 ≤ N ≤ 100
* 1 ≤ M ≤ 4,950
* si is a string of 1 to 15 characters consisting of only uppercase or lowercase letters of the alphabet.
* i ≠ j ⇒ si ≠ sj
* pi ≤ qi
* i ≤ j ⇒ (pi, qi) ≠ (pj, qj) and (pi, qi) ≠ (qj, pj)
* There is no double magic that cannot be activated by constructing any spell logic.

Output

Output the maximum number of double magic types available when you build spell logic.

Examples

Input

4 3
huda
leide
loar
sheza
huda leide
leide loar
loar sheza


Output

10


Input

3 3
torn
siole
dimi
torn siole
torn dimi
siole dimi


Output

9


Input

9 10
riris
soa
elah
clar
arma
memori
neoles
qhaon
clue
clar riris
riris memori
riris neoles
soa clar
soa memori
neoles elah
elah qhaon
neoles qhaon
clue riris
arma elah


Output

54

Solution (in CPP):

Solution:
#include <cassert>// c
#include <iostream>// io
#include <iomanip>
#include <fstream>
#include <sstream>
#include <vector>// container
#include <map>
#include <set>
#include <queue>
#include <bitset>
#include <stack>
#include <algorithm>// other
#include <complex>
#include <numeric>
#include <functional>
#include <random>
#include <regex>
using namespace std;

typedef int32_t i32;typedef int64_t i64;typedef i64 ll;typedef uint32_t uint;typedef uint64_t ull;

#define ALL(c) (begin(c)),(end(c))
#define REP(i,n) FOR(i,0,n)
#define REPr(i,n) FORr(i,0,n)
#define FOR(i,l,r) for(int i=(int)(l);i<(int)(r);++i)
#define FORr(i,l,r) for(int i=(int)(r)-1;i>=(int)(l);--i)
#define EACH(it,o) for(auto it = (o).begin(); it != (o).end(); ++it)
#define IN(l,v,r) ((l)<=(v) && (v)<(r))

//debug
#define DUMP(x)  cerr << #x << " = " << (x)
#define DUMPLN(x)  DUMP(x) <<endl
#define DEBUG(x) DUMP(x) << LINE() << " " << __FILE__
#define DEBUGLN(x) DEBUG(x)<<endl
#define LINE()    cerr<< " (L" << __LINE__ << ")"
#define LINELN()    LINE()<<endl
#define CHECK(exp,act)  if(exp!=act){DUMPLN(exp);DEBUGLN(act);}
#define STOP(e)  CHECK(e,true);if(!(e)) exit(1);

class range {
private:
	struct Iter{
		int v;
		int operator*(){return v;}
		bool operator!=(Iter& itr) {return v < itr.v;}
		void operator++() {++v;}
	};
	Iter i, n;
public:
	range(int n) : i({0}), n({n}) {}
	range(int i, int n) : i({i}), n({n}) {}
	Iter& begin() {return i;}
	Iter& end() {return n;}
};

//output
template<typename T> ostream& operator << (ostream& os, const vector<T>& as){for(int i:range(as.size())){if(i!=0)os<<" "; os<<as[i];}return os;}
template<typename T> ostream& operator << (ostream& os, const vector<vector<T>>& as){for(int i:range(as.size())){if(i!=0)os<<endl; os<<as[i];}return os;}
template<typename T1,typename T2> ostream& operator << (ostream& os, const pair<T1,T2>& p){os<<p.first<<" "<<p.second;return os;}
template<typename K,typename V> ostream& operator << (ostream& os, const map<K,V>& m){bool isF=true;for(auto& p:m){if(!isF)os<<endl;os<<p;isF=false;}return os;}
template<typename T1> ostream& operator << (ostream& os, const tuple<T1>& t){os << get<0>(t);return os;}
template<typename T1,typename T2> ostream& operator << (ostream& os, const tuple<T1,T2>& t){os << get<0>(t)<<" "<<get<1>(t);return os;}
template<typename T1,typename T2,typename T3> ostream& operator << (ostream& os, const tuple<T1,T2,T3>& t){os << get<0>(t)<<" "<<get<1>(t)<<" "<<get<2>(t);return os;}
template<typename T1,typename T2,typename T3,typename T4> ostream& operator << (ostream& os, const tuple<T1,T2,T3,T4>& t){os << get<0>(t)<<" "<<get<1>(t)<<" "<<get<2>(t)<<" "<<get<3>(t);return os;}
template<typename T1,typename T2,typename T3,typename T4,typename T5> ostream& operator << (ostream& os, const tuple<T1,T2,T3,T4,T5>& t){os << get<0>(t)<<" "<<get<1>(t)<<" "<<get<2>(t)<<" "<<get<3>(t)<<" "<<get<4>(t);return os;}
template<typename T1,typename T2,typename T3,typename T4,typename T5,typename T6> ostream& operator << (ostream& os, const tuple<T1,T2,T3,T4,T5,T6>& t){os << get<0>(t)<<" "<<get<1>(t)<<" "<<get<2>(t)<<" "<<get<3>(t)<<" "<<get<4>(t)<<" "<<get<5>(t);return os;}
template<typename T1,typename T2,typename T3,typename T4,typename T5,typename T6,typename T7> ostream& operator << (ostream& os, const tuple<T1,T2,T3,T4,T5,T6,T7>& t){os << get<0>(t)<<" "<<get<1>(t)<<" "<<get<2>(t)<<" "<<get<3>(t)<<" "<<get<4>(t)<<" "<<get<5>(t)<<" "<<get<6>(t);return os;}

//input
char tmp[1000];
#define nextInt(n) scanf("%d",&n)
#define nextLong(n) scanf("%I64d",&n) //I64d
#define nextDouble(n) scanf("%lf",&n) 
#define nextChar(n) scanf("%c",&n)
#define nextString(n) scanf("%s",tmp);n=tmp

// values
template<class T> T INF(){assert(false);};
template<> int INF<int>(){return 1<<28;};
template<> ll INF<ll>(){return 1LL<<58;};
template<> double INF<double>(){return 1e16;};

//O(V+E)
typedef vector<vector<int>> Graph;
class Bridge{
public:
	int N;Graph g;
	vector<int> ord,low;vector<bool> vis;
	stack<int> roots,st;vector<bool> S;
	void dfs(int v,int p,int &oi,int &gi){
		vis[v]=true;ord[v]=low[v]=oi++;st.push(v);S[v]=true;roots.push(v);
		for(int to:g[v]){
			if(!vis[to]) dfs(to,v,oi,gi);
			else if(to != p && S[to])
				while(ord[roots.top()] > ord[to])roots.pop();
		}
		if(v != roots.top()) return;

		bridges.push_back(make_pair(min(v,p),max(v,p)));
		while(true){
			int w=st.top();st.pop();S[w]=false;
			cmp[w]=gi;
			if(v==w)break;
		}
		gi++;roots.pop();
	}
public:
	vector<int> cmp;
	vector<pair<int,int>> bridges;
	Bridge(int N):N(N){
		g=Graph(N);ord=low=cmp=vector<int>(N);vis=S=vector<bool>(N);
	}
	void add_edge(int f,int t){
		g[f].push_back(t);g[t].push_back(f);
	}
	void bridge(){
		int oi=0,gi=0;REP(v,N)if(!vis[v])dfs(v,-1,oi,gi);
	}
	bool same(int i,int j){return cmp[i]==cmp[j];}
};

class Main{
	public:

	int n,m;
	Graph g;
	vector<int> ch;
	int dfs(int v,int p){
		int res = 0;
		for(int to:g[v])if(to!=p)res += dfs(to,v);
		ch[v] = wmap[v];
		for(int to:g[v])if(to!=p)ch[v] += ch[to];
		res += wmap[v] * ch[v];
		if(p!=-1)return res;

		// v is root
		// Y -> r -> X
		vector<bool> exval(n+1);exval[0]=true;
		for(int to:g[v])if(to!=p){
			REPr(val,n+1)if(IN(0,val-ch[to],n+1))
				exval[val] = exval[val] | exval[val-ch[to]];
		}
		// max(|Y| * |X|)
		int sum = n - wmap[v];
		int Mv = 0;REP(val,n+1)if(exval[val] && val<=sum)Mv=max(Mv,val*(sum-val));
		return res + Mv;
	}

	map<int,int> wmap;
	void run(){
		nextInt(n);nextInt(m);
		map<string,int> stoi;
		REP(i,n){string key;nextString(key);stoi[key]=i;}
		Bridge bg(n);
		REP(i,m){
			string f,t;nextString(f);nextString(t);
			bg.add_edge(stoi[f],stoi[t]);
		}
		bg.bridge();

		//make tree
		REP(v,n)wmap[bg.cmp[v]]++;
		g = Graph(n);
		REP(v,n)for(int to:bg.g[v])if(bg.cmp[v]!=bg.cmp[to]){
			g[bg.cmp[v]].push_back(bg.cmp[to]);
		}
		REP(v,n){
			sort(ALL(g[v]));g[v].erase(unique(ALL(g[v])),g[v].end());
		}

		ch=vector<int>(n);
		// ~W ...reverse graph of W
		// 以下のように向きを揃えた方がよい．
		// count( W <- x -> V ) <= count( ~W -> x -> V )
		// （次数3以上も同様．）
		// count( W,W' <- x -> V ) <= count( ~W,~W' -> x -> V )
		// ∴ rootをfixして、各 child_i について root と child_i の向きを child_i 以降の子に伝搬させて考えてよい．
		int Mv=0;REP(v,n)Mv=max(Mv,dfs(bg.cmp[v],-1));
		cout << Mv <<endl;
	}
};

int main(){
	cout <<fixed<<setprecision(20);
	cin.tie(0);
	ios::sync_with_stdio(false);
	Main().run();
	return 0;
}