普通に塗って試せばいい。
グラフは連結だし、頂点の数も充分に小さいっぽい。
#include <algorithm>
#include <complex>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <vector>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#define REP(i, n) for(int i=0; i<(int)n; ++i)
#define FOR(i, c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(),(c).end()
#define each(i, c) FOR(i, c)
typedef long long int lli;
using namespace std;
const int N = 1000;
int color[N];
const int C = 4;
int w[C];
vector<int> g[N];
bool valid(int src, int c)
{
for (int i = 0; i < g[src].size(); ++i) {
int dst = g[src][i];
if (color[dst] == c) return false;
}
return true;
}
int get_value(int size)
{
int sum = 0;
for (int i = 0; i < size; ++i) {
for (int j = 0; j < g[i].size(); ++j) {
int src = i;
int dst = g[i][j];
if (src < dst) {
int diff = color[src] - color[dst];
sum += diff * diff;
}
}
}
return sum;
}
int rec(int node, int size)
{
if (node == size) {
return get_value(size);
}
int mx = 0;
for (int i = 0; i < C; ++i) {
if (!valid(node, w[i])) continue;
color[node] = w[i];
mx = max(mx, rec(node + 1, size));
color[node] = -1;
}
return mx;
}
int main(int argc, char *argv[])
{
int node, edge;
while (cin >> node >> edge) {
fill(g, g + N, vector<int>());
for (int i = 0; i < C; ++i) {
cin >> w[i];
}
for (int i = 0; i < edge; ++i) {
int a, b;
cin >> a >> b;
--a;
--b;
g[a].push_back(b);
g[b].push_back(a);
}
fill(color, color + N, -1);
cout << rec(0, node) << endl;
}
return 0;
}