This documentation is automatically generated by online-judge-tools/verification-helper
#define PROBLEM "https://judge.yosupo.jp/problem/enumerate_cliques"
#include <iostream>
#include <atcoder/modint>
using mint = atcoder::modint998244353;
#include "library/graph/enumerate_cliques.hpp"
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n, m;
std::cin >> n >> m;
std::vector<int> x(n);
for (int &e : x) std::cin >> e;
std::vector<std::vector<int>> g(n);
for (int i = 0; i < m; ++i) {
int u, v;
std::cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
mint ans = 0;
suisen::enumerate_cliques(
g,
[&ans, &x](const std::vector<int> &clique) {
mint prod = 1;
for (int i : clique) prod *= mint::raw(x[i]);
ans += prod;
}
);
std::cout << ans.val() << '\n';
return 0;
}#line 1 "test/src/graph/enumerate_cliques/enumerate_cliques.test.cpp"
#define PROBLEM "https://judge.yosupo.jp/problem/enumerate_cliques"
#include <iostream>
#include <atcoder/modint>
using mint = atcoder::modint998244353;
#line 1 "library/graph/enumerate_cliques.hpp"
#include <algorithm>
#include <numeric>
#include <vector>
namespace suisen {
/**
* Type Parameters
* - CliqueConsumer : type of consumer function std::vector<int> -> void
*
* Parameters
* - std::vector<std::vector<int>> g : simple undirected graph
* - CliqueConsumer fun
*
* Requirements
* - v in g[u] <=> u in g[v]
*
* Complexity
* - time : O(2^sqrt(2M) * N + (sum of size of cliques)) = O(2^sqrt(2M) * N * sqrt(2M)) ?
* - space : O(N + M)
*/
template <typename CliqueConsumer>
void enumerate_cliques(std::vector<std::vector<int>> g, CliqueConsumer &&fun) {
const int n = g.size();
// sort by degree
std::vector<int> ord(n), idx(n);
std::iota(ord.begin(), ord.end(), 0);
std::sort(ord.begin(), ord.end(), [&](int i, int j) { return g[i].size() < g[j].size(); });
for (int i = 0; i < n; ++i) idx[ord[i]] = i;
for (int i = 0; i < n; ++i) {
g[i].erase(std::remove_if(g[i].begin(), g[i].end(), [&](int j) { return idx[j] < idx[i]; }), g[i].end());
std::sort(g[i].begin(), g[i].end(), [&](int x, int y) { return idx[x] < idx[y]; });
}
std::vector<int> id(n, -1), inv_id(n);
std::vector<int> clique(n);
for (int i : ord) {
const int l = g[i].size();
for (int p = 0; p < l; ++p) {
int j = g[i][p];
inv_id[id[j] = p] = j;
}
std::vector<int> st(l);
for (int p = 0; p < l; ++p) {
st[p] = (1 << (p + 1)) - 1;
for (int j : g[g[i][p]]) if (int k = id[j]; k >= 0) st[p] |= 1 << k;
}
std::vector<int>::iterator it = clique.begin();
*it++ = i;
fun(std::vector<int>(clique.begin(), it));
std::vector<int> intersec(l, (1 << l) - 1);
for (int c = 1; c < 1 << l; ++c) {
const int k = __builtin_ctz(c);
std::fill(intersec.begin(), intersec.begin() + k, intersec[k] &= st[k]);
*(it -= k)++ = inv_id[k];
if ((intersec[0] & c) == c) fun(std::vector<int>(clique.begin(), it));
}
for (int j : g[i]) id[j] = -1;
}
}
} // namespace suisen
#line 9 "test/src/graph/enumerate_cliques/enumerate_cliques.test.cpp"
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n, m;
std::cin >> n >> m;
std::vector<int> x(n);
for (int &e : x) std::cin >> e;
std::vector<std::vector<int>> g(n);
for (int i = 0; i < m; ++i) {
int u, v;
std::cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
mint ans = 0;
suisen::enumerate_cliques(
g,
[&ans, &x](const std::vector<int> &clique) {
mint prod = 1;
for (int i : clique) prod *= mint::raw(x[i]);
ans += prod;
}
);
std::cout << ans.val() << '\n';
return 0;
}