#include "bits/stdc++.h"
using namespace std;

#define rep(i,n) for (int i=0;i<(n);i++)
#define rep2(i,a,b) for (int i=(a);i<(b);i++)

const int inf = 1e9;

int n, m;
int deg_lim;
vector<vector<int>> A;
int ma = 0;

vector<int> calcDeg(const vector<bool>& alive) {
    vector<int> deg(n);
    rep(i, n) {
        if (!alive[i]) continue;
        rep(j, n) {
            if (i != j && alive[j] && A[i][j] > 0) {
                deg[i]++;
            }
        }
    }
    return deg;
}

int findVertex(const vector<bool>& alive, const vector<int>& deg) {
    // cerr << "[findVertex]" << endl;
    // cerr << "alive:";
    // rep(i, n) {
    //     cerr << " " << alive[i];
    // }
    // cerr << endl;
    // cerr << "deg:";
    // rep(i, n) {
    //     cerr << " " << deg[i];
    // }
    // cerr << endl;

    rep(i, n) {
        if (alive[i] && deg[i] < deg_lim) {
            return i;
        }
    }
    assert(false);
}

/*
bool isClique(int state, const vector<int>& ids) {
    int k = ids.size();
    if (k == 1) return true;
    rep(i, k) {
        if (!((state >> i) & 1)) continue;
        rep2(j, i + 1, k) {
            if (!((state >> j) & 1)) continue;
            if (A[ids[i]][ids[j]] == 0) return false;
        }
    }
    return true;
}
*/

int eval(int state, const vector<int>& ids) {
    int k = ids.size();

    // cerr << "[eval]" << endl;
    // cerr << bitset<3>(state) << endl;
    // cerr << "ids:";
    // rep(i, k) {
    //     cerr << " " << ids[i];
    // }
    // cerr << endl;

    assert(__builtin_popcount(state) > 0);
    if (__builtin_popcount(state) == 1) return 0;

    int score = 0;
    rep(i, k) {
        if (!((state >> i) & 1)) continue;
        int mi = inf;
        rep(j, k) {
            if (i == j) continue;
            if (!((state >> j) & 1)) continue;
            if (A[ids[i]][ids[j]] == 0) return -1;
            mi = min(mi, A[ids[i]][ids[j]]);
        }
        assert(mi != inf);
        score += mi;
    }
    return score;
}

void update(int state, const vector<int>& ids) {
    // if (!isClique(state, ids)) return;
    ma = max(ma, eval(state, ids));
}

void genBrute(const vector<bool>& alive) {
    // cerr << "[genBrute]" << endl;
    vector<int> ids;
    rep(i, n) {
        if (alive[i]) ids.emplace_back(i);
    }
    int k = ids.size();
    assert(k > 0);
    assert(k < 15);
    rep2(state, 1, 1 << k) {
        update(state, ids);
    }
}

void genBruteWith(const vector<bool>& alive, int v) {
    // cerr << "[genBruteWith]" << endl;
    vector<int> ids;
    rep(i, n) {
        if (i != v && alive[i] && A[i][v] > 0) ids.emplace_back(i);
    }
    ids.emplace_back(v);
    int k = ids.size();

    // cerr << "ids:";
    // rep(i, k) {
    //     cerr << " " << ids[i];
    // }
    // cerr << endl;

    rep(state, 1 << (k - 1)) {
        update(state | (1 << (k - 1)), ids);
    }
}

bool existAlive(const vector<bool>& alive) {
    rep(i, n) {
        if (alive[i]) return true;
    }
    return false;
}

void genClique(vector<bool>& alive) {
    // cerr << "[genClique]" << endl;
    if (!existAlive(alive)) return;
    vector<int> deg = calcDeg(alive);
    int ma_deg = *max_element(deg.begin(), deg.end());
    if (ma_deg >= deg_lim) {
        // cerr << "- Case 1" << endl;
        genBrute(alive);
    }
    else {
        // cerr << "- Case 2" << endl;
        int v = findVertex(alive, deg);
        // cerr << "v = " << v << endl;
        genBruteWith(alive, v);
        alive[v] = false;
        genClique(alive);
        alive[v] = true;
    }
}

int main() {
    cin >> n >> m;
    deg_lim = sqrt(2 * m) + 1;
    // cerr << "deg_lim = " << deg_lim << endl;
    A.assign(n, vector<int>(n));
    rep(i, m) {
        int a, b, c;
        cin >> a >> b >> c;
        a--; b--;
        A[a][b] = c;
        A[b][a] = c;
    }

    vector<bool> alive(n, true);
    genClique(alive);

    cout << ma << endl;
}

Measured memory_bytes: 3244