#include #include #include using namespace std; using namespace __gnu_pbds; #define int long long int template using ordered_set = tree, rb_tree_tag, tree_order_statistics_node_update>; #define ld long double #define nl cout << "\n"; #define getunique(v) \ { \ sort(v.begin(), v.end()); \ v.erase(unique(v.begin(), v.end()), v.end()); \ } #define forn(a, b) for (int i = a; i < b; i++) #define __builtin_popcountll __builtin_popcountll #define __builtin_clzll __builtin_clzll #define __builtin_ctzll __builtin_ctzll #define yesno(b) cout << ((b) ? "YES" : "NO"); #define pii pair #define mp(a, b) make_pair(a, b) #define pb push_back #define all(a) a.begin(), a.end() #define vi vector #define hhh cout << "here" << endl; #define mod1 1000000007 #define mod2 998244353 const int inf = 1e17 + 1; #define FL(i, a, n) for (int i = a; i < n; i++) #define FR(i, a, n) for (int i = a; i >= n; i--) const int mod = mod2; struct DSU { vector par, sz; DSU(int n) { par.resize(n + 1); sz.resize(n + 1); forn(0, n) { par[i] = i, sz[i] = 1; } } void clear(int n) { for (int i = 0; i < n; i++) { par[i] = i; sz[i] = 1; } } int get(int x) { // path compression if (par[x] != x) par[x] = get(par[x]); return par[x]; } bool unite(int x, int y) { // union-by-rank x = get(x), y = get(y); if (x == y) return 0; if (sz[x] < sz[y]) swap(x, y); sz[x] += sz[y], par[y] = x; return 1; } }; void solve() { int n, m; cin >> n >> m; vi a(n); forn(0, n) cin >> a[i]; DSU dsu(n); forn(0, m) { int u, v; cin >> u >> v; u--, v--; dsu.unite(u, v); } map mp; forn(0, n) { int p = dsu.get(i); mp[p] = 0; } forn(0, n) { int p = dsu.get(i); mp[p] += a[i]; mp[p] %= mod; } int ans = 1; forn(0, n) { int p = dsu.get(i); ans *= mp[p]; ans %= mod; } cout << ans; } signed main() { ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); // freopen("input.txt", "r", stdin); // freopen("output.txt", "w", stdout); int t = 1; // cin >> t; while (t--) { solve(); nl; } return 0; }