Problem:
Problem J: Cluster Network
Problem
マイヅ大学にある大規模クラスタ
†
型スーパーコンピュータ（通称「SAKURA」）のクラスタは、$N$台のコンピュータ（ノード）と$M$本の相互に通信が可能な物理的通信路で構成される。また、各ノードにはそれぞれ1から$N$までの識別番号が割り当てられている。
この度SAKURAの利用を大学関係者だけでなく、県内の企業にも認めることとなった。それに伴い、SAKURAを構成する各ノードを点検する必要がある。しかし、SAKURAの利用スケジュールは数ヶ月先まで埋まっているので、点検中もシステム全体を停止させることはできない。そこで、ノードを1日に1台ずつ順番に点検する。
点検は$N$日にわたって行われ、$i$日目にノード$i$を点検する。このとき、点検するノードとそのノードに直接接続されている通信路をSAKURAのクラスタから切り離す。それによって、SAKURAのクラスタ全体は1つ以上のクラスタに分断されるので、そのうちのいずれかをSAKURAの代わりに運用する。当然、点検中のノードは運用することができない。
複数のクラスタに分断された場合、それらの中で最も「総合性能値」の高いクラスタのみを運用する。各クラスタの「総合性能値」はそれを構成する各ノードに設定された「単体性能値」の和である。
SAKURAを構成するノードの数、通信路の本数と各ノードに設定された「単体性能値」が与えられるので、$i$日目の点検中に運用されるクラスタの「総合性能値」を出力せよ。
†：クラスタとは、1つ以上のコンピュータを結合してひとまとまりにしたシステムのこと。ここでは、物理的通信路で連結なノードの集合とする。
Input
入力は以下の形式で与えられる。
$N$ $M$
$w_1$ $w_2$ ... $w_N$
$u_1$ $v_1$
$u_2$ $v_2$
...
$u_M$ $v_M$
1行目にクラスタを構成するノードの数$N$と通信路の本数$M$が空白区切りで与えられる。
2行目には各ノードの「単体性能値」を表す$N$個の整数が空白区切りで与えられる。$i$番目の整数$w_i$はノード$i$の「単体性能値」を表す。
3行目からの$M$行には各通信路がつなぐ2つのノードの識別番号が空白区切りで与えられる。2+$i$行目の入力では、通信路がノード$u_i$とノード$v_i$を相互につなぐことを表す。
Constraints
入力は以下の条件を満たす。
$2 \leq N \leq 10^5$
$N-1 \leq M \leq min(\frac{N\times(N-1)}{2},10^5)$
$1 \leq w_i \leq 10^6$
$1 \leq u_i, v_i \leq N, u_i \ne v_i$
$(u_i,v_i) \ne (u_j,v_j), (u_i,v_i) \ne (v_j,u_j), i \ne j$
入力は全て整数
Output
出力は$N$行からなる。
$i$行目には、$i$日目に運用されるクラスタの「総合性能値」を出力する。
Sample Input 1
9 10
1 2 3 4 5 6 7 8 9
1 2
2 3
2 4
3 4
4 5
4 6
2 7
7 8
7 9
9 1
Sample Output 1
44
25
42
30
40
39
30
37
36
Sample Input 2
16 19
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
1 2
2 3
3 4
3 5
1 6
6 7
6 8
7 8
8 9
8 10
10 11
11 12
12 10
1 13
13 14
14 15
15 13
14 16
15 16
Sample Output 2
63
122
124
132
131
73
129
86
127
103
125
124
78
122
121
120
Sample Input 3
2 1
1 2
1 2
Sample Output 3
2
1

Submitted solutions:

code_snippet: #define PROBLEM "https://onlinejudge.u-aizu.ac.jp/problems/3022"


#include <cassert>
#include <concepts>
#include <vector>
#include <optional>


#include <cstdint>
#include <cstddef>

namespace zawa {

using i16 = std::int16_t;
using i32 = std::int32_t;
using i64 = std::int64_t;
using i128 = __int128_t;

using u8 = std::uint8_t;
using u16 = std::uint16_t;
using u32 = std::uint32_t;
using u64 = std::uint64_t;

using usize = std::size_t;

} // namespace zawa

namespace zawa {

template <std::integral T>
class BlockCutTree {
public:

    BlockCutTree() = default;

    BlockCutTree(const std::vector<std::vector<T>>& g) : inv_(g.size()) {
        const usize n = g.size();
        std::vector<usize> low(n), ord(n), vs;
        usize time = 1;
        const T INVALID = static_cast<T>(-1);
        auto dfs = [&](auto dfs, T v, T p) -> void {
            low[v] = ord[v] = time++;
            if (g[v].empty()) {
                blocks_.push_back({T{v}});
                return;
            }
            usize deg = 0;
            bool cut = false;
            for (T x : g[v]) {
                if (ord[x]) {
                    low[v] = std::min(low[v], ord[x]);
                }
                else {
                    deg++;
                    dfs(dfs, x, v);
                    low[v] = std::min(low[v], low[x]);
                    if (low[x] >= ord[v]) {
                        std::vector<T> cur{v};
                        cut |= p != INVALID;
                        while (vs.size() and ord[vs.back()] >= ord[x]) {
                            cur.push_back(vs.back());
                            vs.pop_back();
                        }
                        blocks_.push_back(std::move(cur));
                    }
                }
            }
            cut |= p == INVALID and deg >= 2;
            if (cut) cuts_.push_back(v);
            vs.push_back(v);
        };
        for (T i = 0 ; i < static_cast<T>(n) ; i++) if (!ord[i]) 
            dfs(dfs, i, INVALID);
        const usize m = blocks_.size(), k = cuts_.size();
        for (usize i = 0 ; i < k ; i++) inv_[cuts_[i]] = m + i;
        g_.resize(m + k);
        for (usize i = 0 ; i < m ; i++) {
            for (T v : blocks_[i]) if (inv_[v] >= m) {
                g_[i].push_back(inv_[v]);
                g_[inv_[v]].push_back(i);
            }
        }
    }

    inline usize size() const noexcept {
        return g_.size();
    }

    const std::vector<T>& operator[](usize i) const {
        assert(i < size());
        return g_[i];
    }

    enum class Type {
        BLOCK,
        CUT
    };

    Type type(usize i) const {
        assert(i < size());
        return i < blocks_.size() ? Type::BLOCK : Type::CUT;
    }

    const std::vector<std::vector<T>>& blocks() const {
        return blocks_;
    }

    const std::vector<T>& block(usize i) const {
        assert(i < size() and type(i) == Type::BLOCK);
        return blocks_[i];
    }

    const std::vector<T>& cuts() const {
        return cuts_;
    }

    const T cut(usize i) const {
        assert(i < size() and type(i) == Type::CUT);
        return cuts_[i - blocks_.size()];
    }

    std::vector<T> vertices(usize i) const {
        assert(i < size());
        return i < blocks_.size() ? 
            blocks_[i] : std::vector<T>{cuts_[i - blocks_.size()]};
    }

    bool isCut(T v) const {
        assert(v < static_cast<T>(inv_.size()));
        return inv_[v] >= blocks_.size();
    }

    std::optional<usize> cutId(usize i) const {
        assert(i < size());
        return isCut(i) ? std::optional<usize>{inv_[i]} : std::nullopt;
    }

private:

    std::vector<std::vector<T>> blocks_;

    std::vector<T> cuts_;

    std::vector<std::vector<T>> g_;

    std::vector<usize> inv_;
};

} // namespace zawa
using namespace zawa;

#include <iostream>
#include <numeric>
#include <unordered_set>

int main() {
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
    std::ios::sync_with_stdio(false);
    int N, M;
    std::cin >> N >> M;
    std::vector<int> W(N);
    for (auto& w : W) std::cin >> w;
    std::vector<std::vector<int>> g(N);
    for (int i = 0 ; i < M ; i++) {
        int u, v;
        std::cin >> u >> v;
        u--; v--;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    BlockCutTree bct{g};
    const long long sum = std::accumulate(W.begin(), W.end(), 0LL);
    std::vector<long long> ans(N);
    for (int i = 0 ; i < N ; i++) if (!bct.isCut(i)) 
        ans[i] = sum - W[i];
    std::vector<bool> vis(bct.size());
    auto rec = [&](auto rec, int v, int p) -> std::pair<std::unordered_set<int>, long long> {
        vis[v] = true;
        long long s = 0LL;
        std::unordered_set<int> set;
        const int pos = bct.type(v) == decltype(bct)::Type::CUT ? bct.cut(v) : -1;
        for (int x : bct[v]) if (x != p) {
            auto [st, k] = rec(rec, x, v);
            if (pos != -1) ans[pos] = std::max(ans[pos], k - (st.contains(pos) ? W[pos] : 0));
            if (set.size() < st.size()) {
                std::swap(set, st);
                std::swap(s, k);
            }
            for (int ch : st) if (!set.contains(ch)) {
                s += W[ch];
                set.insert(ch);
            }
        }
        for (int cur : bct.vertices(v)) {
            if (!set.contains(cur)) {
                set.insert(cur);
                s += W[cur];
            }
        }
        if (pos != -1) ans[pos] = std::max(ans[pos], sum - s);
        return {set, s};
    };
    for (int i = 0 ; i < std::ssize(bct) ; i++) if (!vis[i]) rec(rec, i, -1);
    for (long long i : ans) std::cout << i << '\n';
}
accuracy: 1
time_ms: 170
memory_kb: 34320
final_rank: 18

code_snippet: #line 1 "/home/y_midori/cp/test/test.test.cpp"
#define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=3022"
#line 2 "template.hpp"
// #pragma GCC target("avx2")
// #pragma GCC optimize("O3")
// #pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
using namespace std;
template <class T>
concept Streamable = requires(ostream os, T &x) { os << x; };
template <class mint>
concept is_modint = requires(mint &x) {
    { x.val() } -> std::convertible_to<int>;
};
#ifdef LOCAL
#include <debug.hpp>
#else
#define debug(...)
#endif
template <Streamable T> void print_one(const T &value) { cout << value; }
template <is_modint T> void print_one(const T &value) { cout << value.val(); }
void print() { cout << '\n'; }
template <class T, class... Ts> void print(const T &a, const Ts &...b) {
    print_one(a);
    ((cout << ' ', print_one(b)), ...);
    cout << '\n';
}
template <ranges::range Iterable>
    requires(!Streamable<Iterable>)
void print(const Iterable &v) {
    for(auto it = v.begin(); it != v.end(); ++it) {
        if(it != v.begin())
            cout << " ";
        print_one(*it);
    }
    cout << '\n';
}
using vi = vector<int>;
using vii = vector<vector<int>>;
using pii = pair<int, int>;
using ll = long long;
using vl = vector<ll>;
using vll = vector<vl>;
using pll = pair<ll, ll>;
#define all(v) begin(v), end(v)
#define UNIQUE(v) ranges::sort(v), v.erase(unique(all(v)), end(v))
template <typename T> inline bool chmax(T &a, T b) {
    return ((a < b) ? (a = b, true) : (false));
}
template <typename T> inline bool chmin(T &a, T b) {
    return ((a > b) ? (a = b, true) : (false));
}
// https://trap.jp/post/1224/
template <class... T> constexpr auto min(T... a) {
    return min(initializer_list<common_type_t<T...>>{a...});
}
template <class... T> constexpr auto max(T... a) {
    return max(initializer_list<common_type_t<T...>>{a...});
}
template <class... T> void input(T &...a) { (cin >> ... >> a); }
template <class T> void input(vector<T> &a) {
    for(T &x : a)
        cin >> x;
}
#define INT(...)                                                               \
    int __VA_ARGS__;                                                           \
    input(__VA_ARGS__)
#define LL(...)                                                                \
    long long __VA_ARGS__;                                                     \
    input(__VA_ARGS__)
#define STR(...)                                                               \
    string __VA_ARGS__;                                                        \
    input(__VA_ARGS__)
#define REP1(a) for(ll i = 0; i < a; i++)
#define REP2(i, a) for(ll i = 0; i < a; i++)
#define REP3(i, a, b) for(ll i = a; i < b; i++)
#define REP4(i, a, b, c) for(ll i = a; i < b; i += c)
#define overload4(a, b, c, d, e, ...) e
#define rep(...) overload4(__VA_ARGS__, REP4, REP3, REP2, REP1)(__VA_ARGS__)
#define rep1(i, n) for(ll i = 1; i <= ((ll)n); ++i)
ll inf = 3e18;
vl dx = {1, -1, 0, 0};
vl dy = {0, 0, 1, -1};
template <class T> T floor(T x, T y) {
    return x / y - ((x ^ y) < 0 and x % y);
}
template <class T> T ceil(T x, T y) {
    return y < 0 ? floor(-x + -y - 1, -y) : floor(x + y - 1, y);
}
// yの符号に関わらず非負で定義 \bmod:texコマンド
template <class T> T bmod(T x, T y) {
    T m = x % y;
    return (m < 0) ? m + (y > 0 ? y : -y) : m;
}
#line 3 "graph/graph-template.hpp"
/**
 * @brief Graph Template(グラフテンプレート)
 * @see https://ei1333.github.io/library/graph/graph-template.hpp
 */
template <class T = ll> struct Edge {
    int from, to;
    T cost;
    int idx;
    Edge() = default;
    Edge(int from, int to, T cost = 1, int idx = -1)
        : from(from), to(to), cost(cost), idx(idx) {}
    Edge &operator=(const int &x) {
        to = x;
        return *this;
    }
    operator int() const { return to; }
};
template <class T = ll> struct Graph {
    using cost_type = T;
    vector<vector<Edge<T>>> g;
    int es; // edge_size
    Graph() = default;
    explicit Graph(int n) : g(n), es(0) {};
    int size() const { return ssize(g); }
    void add_directed_edge(int from, int to, T cost = 1) {
        g[from].emplace_back(from, to, cost, es++);
    }
    void add_edge(int from, int to, T cost = 1) {
        g[from].emplace_back(from, to, cost, es);
        g[to].emplace_back(to, from, cost, es++);
    }
    vector<Edge<T>> &operator[](const int &k) { return g[k]; }
    const vector<Edge<T>> &operator[](const int &k) const { return g[k]; }
    void read(int m, int padding = -1, bool weighted = false,
              bool directed = false) {
        for(int i = 0; i < m; ++i) {
            int a, b;
            T c(1);
            cin >> a >> b;
            a += padding;
            b += padding;
            if(weighted)
                cin >> c;
            if(directed)
                add_directed_edge(a, b, c);
            else
                add_edge(a, b, c);
        }
    }
};
#line 4 "graph/block-cut-tree.hpp"
/**
 * @brief ブロックカット木的な
 * https://maspypy.github.io/library/graph/block_cut.hpp
 * https://twitter.com/noshi91/status/1529858538650374144
 * N頂点の無向グラフがC個の二重連結成分を持つとき(N+C)頂点の森を作る
 * [0,N)のidxは元のグラフの頂点を表し[N,N+C)のidxは二重連結成分を表す
 * 辺(u,N+v)は頂点uがv番目の二重連結成分に属することを表す
 * 関節点<->次数2以上
 */
template <class G> Graph<bool> block_cut_tree(const G &g) {
    int n = g.size();
    Graph<bool> tree(n);
    vector<int> low(n, -1), ord(n, -1);
    int id = 0;
    vector<int> tmp;
    tree.g.reserve(2 * n);
    tmp.reserve(n);
    auto dfs = [&](auto &dfs, int cur, int p) -> void {
        ord[cur] = low[cur] = id++;
        tmp.emplace_back(cur);
        int cnt = 0;
        for(auto &to : g[cur]) {
            if(to == p)
                continue;
            if(ord[to] == -1) {
                int sz = ssize(tmp);
                ++cnt;
                dfs(dfs, to, cur);
                chmin(low[cur], low[to]);
                if((p == -1 and cnt > 1) or (p != -1 and low[to] >= ord[cur])) {
                    int k = tree.size();
                    tree.g.emplace_back();
                    tree.add_edge(cur, k);
                    while(ssize(tmp) > sz) {
                        tree.add_edge(tmp.back(), k);
                        tmp.pop_back();
                    }
                }
            } else {
                chmin(low[cur], ord[to]);
            }
        }
        if(p == -1) {
            int k = tree.size();
            tree.g.emplace_back();
            for(auto &i : tmp)
                tree.add_edge(i, k);
            tmp.clear();
        }
    };
    for(int i = 0; i < n; ++i) {
        if(ord[i] == -1)
            dfs(dfs, i, -1);
    }
    return tree;
}
#line 5 "/home/y_midori/cp/test/test.test.cpp"
void solve() {
    INT(n, m);
    vector<ll> v(n);
    input(v);
    Graph<bool> g(n);
    g.read(m);
    auto bct = block_cut_tree(g);
    int N = bct.size();
    vector<ll> sub = v;
    sub.resize(N, 0);
    vector<int> par(N, -1);
    auto dfs = [&](auto &dfs, int cur, int p) -> ll {
        par[cur] = p;
        for(auto &to : bct[cur]) {
            if(to != p) {
                sub[cur] += dfs(dfs, to, cur);
            }
        }
        return sub[cur];
    };
    ll sum = dfs(dfs, 0, -1);
    for(int i = 0; i < n; ++i) {
        ll ans = 0;
        ll tmp = 0;
        for(auto &to : bct[i]) {
            if(to != par[i]) {
                chmax(ans, sub[to]);
                tmp += sub[to];
            }
        }
        if(par[i] != -1) {
            chmax(ans, sum - tmp - v[i]);
        }
        print(ans);
    }
}
int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    solve();
}
accuracy: 1
time_ms: 40
memory_kb: 28500
final_rank: 10

code_snippet: // AOJ #3022 Cluster Network
// 2025.4.1

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

#define gc() getchar_unlocked()
#define pc(c) putchar_unlocked(c)

int Cin() {
	int n = 0, c = gc();
	do n = 10*n + (c & 0xf), c = gc(); while (c >= '0');
	return n;
}

void Cout(ll n) {
	char b[30];
	if (!n) pc('0');
	else {
		if (n < 0) pc('-'), n = -n;
		int i = 0; while (n) b[i++] = n % 10 + '0', n /= 10;
		while (i--) pc(b[i]);
	}
	pc('\n');
}

int n, m, t;
vector<int> d, low;
vector<ll> dp, ans, w;
vector<bool> art;
vector<ll> sepSum, sepMax;
vector<vector<int>> g;

void dfs(int u, int par) {
    d[u] = low[u] = ++t;
    dp[u] = w[u];
    int cnt = 0;
    for (int v : g[u]) {
        if (v == par) continue;
        if (!d[v]) {
            cnt++;
            dfs(v, u);
            dp[u] += dp[v];
            low[u] = min(low[u], low[v]);
            if (low[v] >= d[u]) {
                art[u] = true;
                sepSum[u] += dp[v];
                sepMax[u] = max(sepMax[u], dp[v]);
            }
        } else low[u] = min(low[u], d[v]);
    }
    if (par == -1 && cnt < 2) art[u] = false;
}

int main(){
    n = Cin(), m = Cin();
    w.resize(n+1);
    dp.assign(n+1, 0);
    ans.assign(n+1, 0);
    d.assign(n+1, 0);
    low.assign(n+1, 0);
    art.assign(n+1, false);
    sepSum.assign(n+1, 0);
    sepMax.assign(n+1, 0);
    g.assign(n+1, vector<int>());

    for (int i = 1; i <= n; i++) w[i] = Cin();
    for (int i = 0; i < m; i++){
        int u = Cin(), v = Cin();
        g[u].push_back(v);
        g[v].push_back(u);
    }

    dfs(1, -1);

    ll S = 0;
    for (int i = 1; i <= n; i++) S += w[i];

    for (int u = 1; u <= n; u++){
        if (!art[u]) ans[u] = S - w[u];
        else if (d[u] == 1) ans[u] = sepMax[u];
        else ans[u] = max(S - w[u] - sepSum[u], sepMax[u]);
    }

    for (int i = 1; i <= n; i++) Cout(ans[i]);
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 13808
final_rank: 1

code_snippet: //
// Low-Link を用いた橋列挙と、二重辺連結成分分解・二重頂点連結成分分解
//
// cf.
//   hos: グラフ探索アルゴリズムとその応用
//     http://hos.ac/slides/20110504_graph.pdf
//
// verified:
//   Yosupo Library Checker - Two-Edge-Connected Components
//     https://judge.yosupo.jp/problem/two_edge_connected_components
//
//   Yosupo Library Checker - Biconnected Components
//     https://judge.yosupo.jp/problem/biconnected_components
//
//   ARC 039 D - 旅行会社高橋君（for 二重辺連結成分分解）
//     https://arc039.contest.atcoder.jp/tasks/arc039_d
//
//   TTPC 2024 DIV1 A - Don't Detect Cycle（for 橋列挙）
//     https://atcoder.jp/contests/ttpc2024_1/tasks/ttpc2024_1_a
//
//   ARC 045 D - みんな仲良し高橋君（for 二重頂点連結成分分解した Block-Cut 木上の DP）
//     https://atcoder.jp/contests/arc045/tasks/arc045_d
//
//   AOJ 3022 Problem J: Cluster Network
//     https://onlinejudge.u-aizu.ac.jp/problems/3022
//


/*
    アイディア: DFS をしたとき、DFS 後退辺は橋とはなりえない
 
    ・ord[v] := 頂点を訪れた順番
    ・low[v] := v から「DFS 木の根から葉へ進む」or「後退辺を葉から根へ進む」ことによって辿り着ける頂点の ord の最小値
 
    DFS で u -> ... -> v と来て、v から u への後退辺があると、このサイクルの low がすべて ord[u] (以下) になる感じ
    このことから、
 
        DFS-search で、辺 v - ch を v -> ch の順に探索したときに、
            辺 v-to が橋　⇔　ord[v] < low[ch]
 */


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


// Edge Class
template<class T> struct Edge {
    int from, to;
    T val;
    Edge() : from(-1), to(-1), val(-1) { }
    Edge(int f, int t, T v = -1) : from(f), to(t), val(v) {}
    friend ostream& operator << (ostream& s, const Edge& e) {
        return s << e.from << "->" << e.to;
    }
};

// graph class
template<class T> struct Graph {
    vector<vector<Edge<T>>> list;
    
    Graph() { }
    Graph(int n) : list(n) { }
    Graph(const Graph<T> &G) : list(G.list) { }
    void init(int n) {
        list.assign(n, vector<Edge<T>>());
    }
    Graph &operator = (const Graph &g) {
        list = g.list;
        return *this;
    }

    const vector<Edge<T>> &operator [] (int i) const { return list[i]; }
    const size_t size() const { return list.size(); }
    const void clear() {
        list.clear();
    }
    const void resize(int n) {
        list.resize(n);
    }

    void add_edge(int from, int to, T val = -1) {
        list[from].push_back(Edge(from, to, val));
        list[to].push_back(Edge(to, from, val));
    }

    friend ostream &operator << (ostream &s, const Graph &G) {
        s << endl;
        for (int i = 0; i < G.size(); ++i) {
            s << i << " -> ";
            for (const auto &e : G[i]) s << e.to << " ";
            s << endl;
        }
        return s;
    }
};

// low-link
template<class T> struct LowLink {
    // results
    vector<int> ord, low;
    vector<int> aps;         // articulation points
    vector<Edge<T>> brs;     // brideges

    // constructor
    LowLink() { }
    LowLink(const Graph<T> &G) {
        solve(G);
    }
    void init(const Graph<T> &G) {
        solve(G);
    }

    // solver
    int dfs(const Graph<T> &G, int t, int v, int p) {
        ord[v] = low[v] = t++;
        int num_of_children = 0;
        bool exist_articulation = false, is_multiple_edge = false;
        for (const auto &e : G[v]) {
            if (ord[e.to] == -1) {
                num_of_children++;
                t = dfs(G, t, e.to, v);
                low[v] = min(low[v], low[e.to]);  // forward edge of DFS-tree
                exist_articulation |= (p != -1) && (low[e.to] >= ord[v]);
                if (ord[v] < low[e.to]) brs.push_back(e);
            } else if (e.to != p || is_multiple_edge) {
                low[v] = min(low[v], ord[e.to]);  // back edge
            } else {
                is_multiple_edge = true;
            }
        }
        if (exist_articulation || (p == -1 && num_of_children > 1)) {
            aps.emplace_back(v);
        }
        return t;
    }

    void solve(const Graph<T> &G) {
        ord.assign(G.size(), -1), low.assign(G.size(), -1);
        for (int v = 0, k = 0; v < (int)G.size(); v++) {
            if (ord[v] == -1) k = dfs(G, k, v, -1);
        }
    }
};

// Two-Edge-Connected Components decomposition
template<class T> struct TwoEdgeConnectedComponentsDecomposition {
    // results
    LowLink<T> ll;
    vector<int> cmp;
    vector<vector<int>> groups, tree;

    // constructor
    TwoEdgeConnectedComponentsDecomposition() { }
    TwoEdgeConnectedComponentsDecomposition(const Graph<T> &G) {
        solve(G);
    }
    void init(const Graph<T> &G) {
        solve(G);
    }

    // solver
    int dfs(const Graph<T> &G, int t, int v, int p) {
        if (p >= 0 && ll.ord[p] >= ll.low[v]) cmp[v] = cmp[p];
        else cmp[v] = t++;
        for (const auto &e : G[v]) {
            if (cmp[e.to] == -1) t = dfs(G, t, e.to, v);
        }
        return t;
    }

    void solve(const Graph<T> &G) {
        ll.init(G);
        cmp.assign(G.size(), -1);
        int t = 0;
        for (int v = 0; v < (int)G.size(); v++) {
            if (cmp[v] == -1) t = dfs(G, t, v, -1);
        }
        groups.resize(t);
        tree.resize(t);
        for (int v = 0; v < (int)G.size(); v++) {
            groups[cmp[v]].push_back(v);
        }
        for (const auto &e : ll.brs) {
            int u = cmp[e.from], v = cmp[e.to];
            tree[u].push_back(v);
            tree[v].push_back(u);
        }
    }
};

// BiConnected Components decomposition
// block-cut tree (aps: 0, 1, ..., A-1, components: A, A+1, ..., A+C-1)
// (A: size of aps, C: num of components)
template<class T> struct BiConnectedComponentsDecomposition {
    // result
    LowLink<T> ll;
    vector<int> id_ap;   // index of the articulation point (size: V)
    vector<int> id_cc;   // index of the connected component (size: V)
    vector<vector<int>> groups;   // biconnected components (size: C)
    vector<vector<int>> tree;     // block-cut tree (size: A + C)

    // intermediate results
    vector<int> seen, finished;
    vector<vector<pair<int, int>>> grouped_edges;
    vector<pair<int, int>> tmp_edges;

    // constructor
    BiConnectedComponentsDecomposition() { }
    BiConnectedComponentsDecomposition(const Graph<T> &G) {
        solve(G);
    }
    void init(const Graph<T> &G) {
        solve(G);
    }

    // getter, original graph to block-cut tree (v: node of orignal graph)
    int is_ap_original_graph(int v) const {
        return (id_ap[v] != -1);
    }
    int get_id(int v) const {
        return (id_ap[v] == -1 ? id_cc[v] : id_ap[v]);
    }

    // getter, block-cut tree to orignal graph（v: node-id of block-cut tree)
    int is_ap(int v) const {
        return (v < ll.aps.size());
    }
    int get_ap(int v) const {
        if (v >= (int)ll.aps.size()) return -1;  // not ap
        else return ll.aps[v];
    }
    int get_size(int v) const {  // including aps
        if (v < (int)ll.aps.size()) return 1;  // ap
        else return groups[v - ll.aps.size()].size();
    }
    vector<int> get_group(int v) const {
        if (v < (int)ll.aps.size()) return vector<int>({ll.aps[v]});  // ap
        else return groups[v - ll.aps.size()];
    }

    // solver
    void dfs(const Graph<T> &G, int v, int p) {
        seen[v] = true;
        if (G[v].empty()) {
            groups.emplace_back(vector<int>({v}));
        }
        for (const auto &e : G[v]) {
            if (e.to == p) continue;
            if (!seen[e.to] || ll.ord[e.to] < ll.ord[v]) {
                tmp_edges.emplace_back(minmax(v, e.to));
            }
            if (!seen[e.to]) {
                dfs(G, e.to, v);
                if (ll.low[e.to] >= ll.ord[v]) {
                    groups.emplace_back(vector<int>({v}));
                    grouped_edges.emplace_back();
                    int ap = v;
                    while (!tmp_edges.empty()) {
                        const auto &e2 = tmp_edges.back();
                        if (!finished[e2.first] && e2.first != ap) {
                            groups.back().emplace_back(e2.first);
                            finished[e2.first] = true;
                        }
                        if (!finished[e2.second] && e2.second != ap) {
                            groups.back().emplace_back(e2.second);
                            finished[e2.second] = true;
                        }
                        grouped_edges.back().emplace_back(e2);
                        tmp_edges.pop_back();
                        if (e2.first == min(v, e.to) && e2.second == max(v, e.to)) break;
                    }
                }
            }
        }
    }

    void solve(const Graph<T> &G) {
        ll.init(G);
        seen.assign(G.size(), false), finished.assign(G.size(), false);
        for (int v = 0; v < (int)G.size(); v++) {
            if (!seen[v]) dfs(G, v, -1);
        }
        id_ap.assign(G.size(), -1), id_cc.assign(G.size(), -1);
        for (int i = 0; i < (int)ll.aps.size(); i++) {
            id_ap[ll.aps[i]] = i;
        }
        tree.assign(ll.aps.size() + grouped_edges.size(), vector<int>());
        vector<int> last(G.size(), -1);
        for (int i = 0; i < (int)grouped_edges.size(); i++) {
            vector<int> st;
            for (auto [u, v] : grouped_edges[i]) {
                st.push_back(u), st.push_back(v);
            }
            for (auto v : st) {
                if (id_ap[v] == -1) {
                    id_cc[v] = i + ll.aps.size();
                } else if (last[v] != i) {
                    tree[i + ll.aps.size()].push_back(id_ap[v]);
                    tree[id_ap[v]].push_back(i + ll.aps.size());
                    last[v] = i;
                }
            }
        }
    }
};



//------------------------------//
// Examples
//------------------------------//

// Yosupo Library Checker - Two-Edge-Connected Components
void YosupoLibraryCheckerTwoEdgeConnectedComponents() {
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);
    int N, M, a, b;
    cin >> N >> M;
    Graph<int> G(N);
    for (int i = 0; i < M; i++) {
        cin >> a >> b;
        G.add_edge(a, b, i);
    }
    TwoEdgeConnectedComponentsDecomposition<int> tecc(G);

    cout << tecc.groups.size() << '\n';
    for (const auto &group : tecc.groups) {
        cout << group.size();
        for (auto v : group) cout << " " << v;
        cout << '\n';
    }
}

// Yosupo Library Checker - BiConnected Components
void YosupoLibraryCheckerBiConnectedComponents() {
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);
    int N, M, a, b;
    cin >> N >> M;
    Graph<int> G(N);
    for (int i = 0; i < M; i++) {
        cin >> a >> b;
        G.add_edge(a, b, i);
    }
    BiConnectedComponentsDecomposition<int> bcc(G);

    cout << bcc.groups.size() << '\n';
    for (const auto &group : bcc.groups) {
        cout << group.size();
        for (auto v : group) cout << " " << v;
        cout << '\n';
    }
}

// ARC 039 D - 旅行会社高橋君
void ARC_039_D() {
    int V, E, s, t;
    cin >> V >> E;
    Graph<int> original_graph(V);
    for (int i = 0; i < E; ++i) {
        cin >> s >> t, s--, t--;
        original_graph.add_edge(s, t, 1);
    }
    TwoEdgeConnectedComponentsDecomposition<int> tecc(original_graph);

    // LCA
    auto tree = tecc.tree;
    int h = 1;
    while ((1<<h) < V) ++h;
    vector<vector<int>> parent(h, vector<int>(V, -1));
    vector<int> depth(V, -1);

    auto dfs = [&](auto dfs, int v, int p, int d) -> void {
        parent[0][v] = p;
        depth[v] = d;
        for (auto to : tree[v]) if (to != p) dfs(dfs, to, v, d+1);
    };

    dfs(dfs, 0, -1, 0);
    for (int i = 0; i+1 < (int)parent.size(); ++i)
        for (int v = 0; v < V; ++v)
            if (parent[i][v] != -1)
                parent[i+1][v] = parent[i][parent[i][v]];

    auto get = [&](int u, int v) -> int {
        if (depth[u] > depth[v]) swap(u, v);
        for (int i = 0; i < (int)parent.size(); ++i)
            if ( (depth[v] - depth[u]) & (1<<i) )
                v = parent[i][v];
        if (u == v) return u;
        for (int i = (int)parent.size()-1; i >= 0; --i) {
            if (parent[i][u] != parent[i][v]) {
                u = parent[i][u];
                v = parent[i][v];
            }
        }
        return parent[0][u];
    };

    auto dist = [&](int u, int v) -> int {
        int lca = get(u, v);
        return abs(depth[u] - depth[lca]) + abs(depth[v] - depth[lca]);
    };
    
    // queries
    int Q, a, b, c;
    cin >> Q;
    for (int _ = 0; _ < Q; ++_) {
        cin >> a >> b >> c, a--, b--, c--;
        a = tecc.cmp[a], b = tecc.cmp[b], c = tecc.cmp[c];
        int ab = dist(a, b);
        int bc = dist(b, c);
        int ac = dist(a, c);
        if (ab + bc == ac) puts("OK");
        else puts("NG");
    }
}

// TTPC 2024 DIV1 A - Don't Detect Cycle
void TTPC_2024_DIV1_A() {
    int T;
    cin >> T;

    while (T--) {
        int N, M, u, v;
        cin >> N >> M;
        Graph<int> G(N);
        for (int i = 0; i < M; i++) {
            cin >> u >> v, u--, v--;
            G.add_edge(u, v, i);
        }

        vector<int> res, former, latter;
        while (true) {
            set<pair<int,int>> ers;

            // erase bridges
            LowLink<int> ll(G);
            for (auto e : ll.brs) {
                former.push_back(e.val);
                ers.insert(minmax(e.from, e.to));
            }

            // erase edges whose endpoints with 2 degree
            vector<int> deg(N, 0);
            for (int v = 0; v < N; v++) {
                for (auto e : G[v]) {
                    if (ers.count(minmax(e.from, e.to))) continue;
                    deg[v]++;
                }
            }
            for (int v = 0; v < N; v++) {
                for (auto e : G[v]) {
                    if (e.from > e.to) continue;
                    if (ers.count(minmax(e.from, e.to))) continue;
                    if (deg[e.from] == 2 && deg[e.to] == 2) {
                        latter.push_back(e.val);
                        ers.insert(minmax(e.from, e.to));
                    }
                }
            }

            if (ers.empty()) break;

            // build new graph
            Graph<int> G2(N);
            for (int v = 0; v < N; v++) {
                for (auto e : G[v]) {
                    if (e.from > e.to) continue;
                    if (ers.count(minmax(e.from, e.to))) continue;
                    G2.add_edge(e.from, e.to, e.val);
                }
            }
            G = G2;
        }

        reverse(latter.begin(), latter.end());
        for (auto v : former) res.push_back(v);
        for (auto v : latter) res.push_back(v);
        if (res.size() < M) {
            cout << -1 << endl;
        } else {
            for (auto id : res) cout << id+1 << " ";
            cout << endl;
        }
    }
}


// Union-Find
struct UnionFind {
    // core member
    vector<int> par, nex;

    // constructor
    UnionFind() { }
    UnionFind(int N) : par(N, -1), nex(N) {
        init(N);
    }
    void init(int N) {
        par.assign(N, -1);
        nex.resize(N);
        for (int i = 0; i < N; ++i) nex[i] = i;
    }
    
    // core methods
    int root(int x) {
        if (par[x] < 0) return x;
        else return par[x] = root(par[x]);
    }
    
    bool same(int x, int y) {
        return root(x) == root(y);
    }
    
    bool merge(int x, int y) {
        x = root(x), y = root(y);
        if (x == y) return false;
        if (par[x] > par[y]) swap(x, y); // merge technique
        par[x] += par[y];
        par[y] = x;
        swap(nex[x], nex[y]);
        return true;
    }
    
    int size(int x) {
        return -par[root(x)];
    }
    
    // get group
    vector<int> group(int x) {
        vector<int> res({x});
        while (nex[res.back()] != x) res.push_back(nex[res.back()]);
        return res;
    }
    vector<vector<int>> groups() {
        vector<vector<int>> member(par.size());
        for (int v = 0; v < (int)par.size(); ++v) {
            member[root(v)].push_back(v);
        }
        vector<vector<int>> res;
        for (int v = 0; v < (int)par.size(); ++v) {
            if (!member[v].empty()) res.push_back(member[v]);
        }
        return res;
    }
    
    // debug
    friend ostream& operator << (ostream &s, UnionFind uf) {
        const vector<vector<int>> &gs = uf.groups();
        for (const vector<int> &g : gs) {
            s << "group: ";
            for (int v : g) s << v << " ";
            s << endl;
        }
        return s;
    }
};

void ARC_045_D() {
    // 入力
    int N;
    cin >> N;
    vector<int> X(N*2+1), Y(N*2+1);
    for (int i = 0; i < N*2+1; i++) cin >> X[i] >> Y[i];

    // 横方向
    using pint = pair<int,int>;
    vector<vector<pint>> xy(N*2+2), yx(N*2+2);
    for (int i = 0; i < N*2+1; i++) {
        xy[X[i]].emplace_back(Y[i], i);
        yx[Y[i]].emplace_back(X[i], i);
    }
    for (int v = 0; v <= N*2+1; v++) {
        sort(xy[v].begin(), xy[v].end());
        sort(yx[v].begin(), yx[v].end());
    }

    // グラフを作る（横・縦に「隣接」「1個飛ばし」のみ辺を張る）
    Graph<int> G(N*2+1);
    for (int v = 0; v <= N*2+1; v++) {
        for (int i = 0; i < xy[v].size(); i++) {
            if (i+1 < xy[v].size()) G.add_edge(xy[v][i].second, xy[v][i+1].second);
            if (i+2 < xy[v].size()) G.add_edge(xy[v][i].second, xy[v][i+2].second);
        }
        for (int i = 0; i < yx[v].size(); i++) {
            if (i+1 < yx[v].size()) G.add_edge(yx[v][i].second, yx[v][i+1].second);
            if (i+2 < yx[v].size()) G.add_edge(yx[v][i].second, yx[v][i+2].second);
        }
    }

    // Block-Cut 木の構築
    BiConnectedComponentsDecomposition<int> bcc(G);

    // グラフ G の各連結成分のサイズを求めて、間接点以外の点の答えを求める
    UnionFind uf(N*2+1);
    for (int v = 0; v < N*2+1; v++) for (auto e : G[v]) uf.merge(e.from, e.to);
    int odd_num = 0;
    for (int v = 0; v < N*2+1; v++) if (uf.root(v) == v && uf.size(v) % 2 == 1) odd_num++;
    if (odd_num > 1) {
        // 奇数サイズの連結成分が複数個ある場合はすべて NG（以降、奇数サイズの連結成分は 1 個とする)
        for (int v = 0; v < N*2+1; v++) cout << "NG" << endl;
        return;
    }
    vector<bool> res(N*2+1, false);
    for (int v = 0; v < N*2+1; v++) {
        // 奇数サイズかつ間接点以外は true (間接点の結果はあとで上書きする)
        if (uf.size(v) % 2 == 1) {
            res[v] = true;
        }
    }

    // Block-Cut 木上の探索により、間接点の答えを求める
    auto tree = bcc.tree;
    vector<bool> seen(tree.size(), false);
    auto dfs = [&](auto dfs, int v, int p) -> int {
        seen[v] = true;

        // 奇数サイズの連結成分を二重頂点連結成分分解してできる Block-Cut 木を
        // 根付き木として探索したとき、各間接点について、
        // ある子頂点が存在して、それを根とする部分木のサイズが奇数ならば、"NG"
        int siz = bcc.get_size(v), odd_num = 0;
        for (auto ch : tree[v]) {
            if (ch == p) continue;
            int tmp = dfs(dfs, ch, v) - 1;
            if (tmp % 2 == 1) odd_num++;
            siz += tmp;
        }
        if (bcc.is_ap(v)) {
            int apv = bcc.get_ap(v);  // Block-cut 木の頂点 v に対応するもとのグラフの頂点
            if (uf.size(apv) % 2 == 1 && odd_num > 0) {
                res[apv] = false;
            }
        }
        return siz;
    };
    for (int v = 0; v < tree.size(); v++) {
        if (seen[v]) continue;
        dfs(dfs, v, -1);
    } 

    // 出力
    for (int v = 0; v < res.size(); v++) {
        if (res[v]) cout << "OK" << endl;
        else cout << "NG" << endl;
    }
}

// AOJ 3022 - Cluster Network
void AOJ_3022() {
    long long N, M, u, v, all = 0;
    cin >> N >> M;
    vector<long long> w(N), res(N, 0);
    for (int i = 0; i < N; i++) cin >> w[i], all += w[i];
    Graph<int> G(N);
    for (int i = 0; i < M; i++) {
        cin >> u >> v, u--, v--;
        G.add_edge(u, v), G.add_edge(v, u);
    }

    // Block-Cut 木上を形成
    BiConnectedComponentsDecomposition<int> bcc(G);

    // 関節点以外について求める
    for (int ov = 0; ov < N; ov++) {
        if (!bcc.is_ap_original_graph(ov)) res[ov] = all - w[ov];
    }

    // 関節点について求める：Block-Cut 木上の DP
    auto tree = bcc.tree;
    vector<long long> sum(tree.size(), 0);
    for (int v = 0; v < tree.size(); v++) {
        const auto &group = bcc.get_group(v);
        for (auto ov : group) sum[v] += w[ov];
    }
    auto rec = [&](auto rec, int v, int p) -> long long {
        const auto &group = bcc.get_group(v);
        long long ma = 0, all_weight = sum[v];
        for (auto ch : tree[v]) {
            if (ch == p) continue;
            long long sub = rec(rec, ch, v);
            if (bcc.is_ap(v)) sub -= sum[v];
            else sub -= sum[ch];
            ma = max(ma, sub), all_weight += sub;
        }

        // 関節点について処理する
        if (bcc.is_ap(v)) {
            int ov = bcc.get_ap(v);
            long long rem = all - all_weight;
            ma = max(ma, rem);
            res[ov] = ma;
        }
        return all_weight;
    };
    rec(rec, 0, -1);

    for (auto val : res) cout << val << endl;
}

int main() {
    //YosupoLibraryCheckerTwoEdgeConnectedComponents();
    //YosupoLibraryCheckerBiConnectedComponents();
    //ARC_039_D();
    //TTPC_2024_DIV1_A();
    //ARC_045_D();
    AOJ_3022();
}
accuracy: 1
time_ms: 120
memory_kb: 45696
final_rank: 17

code_snippet: #include <bits/stdc++.h>
using namespace std;

// Edge Class
template<class T> struct Edge {
    int from, to;
    T val;
    Edge() : from(-1), to(-1), val(-1) { }
    Edge(int f, int t, T v = -1) : from(f), to(t), val(v) {}
    friend ostream& operator << (ostream& s, const Edge& e) {
        return s << e.from << "->" << e.to;
    }
};

// graph class
template<class T> struct Graph {
    vector<vector<Edge<T>>> list;
    
    Graph() { }
    Graph(int n) : list(n) { }
    Graph(const Graph<T> &G) : list(G.list) { }
    void init(int n) {
        list.assign(n, vector<Edge<T>>());
    }
    Graph &operator = (const Graph &g) {
        list = g.list;
        return *this;
    }

    const vector<Edge<T>> &operator [] (int i) const { return list[i]; }
    const size_t size() const { return list.size(); }
    const void clear() {
        list.clear();
    }
    const void resize(int n) {
        list.resize(n);
    }

    void add_edge(int from, int to, T val = -1) {
        list[from].push_back(Edge(from, to, val));
        list[to].push_back(Edge(to, from, val));
    }

    friend ostream &operator << (ostream &s, const Graph &G) {
        s << endl;
        for (int i = 0; i < G.size(); ++i) {
            s << i << " -> ";
            for (const auto &e : G[i]) s << e.to << " ";
            s << endl;
        }
        return s;
    }
};

// low-link
template<class T> struct LowLink {
    // results
    vector<int> ord, low;
    vector<int> aps;         // articulation points
    vector<Edge<T>> brs;     // brideges

    // constructor
    LowLink() { }
    LowLink(const Graph<T> &G) {
        solve(G);
    }
    void init(const Graph<T> &G) {
        solve(G);
    }

    // solver
    int dfs(const Graph<T> &G, int t, int v, int p) {
        ord[v] = low[v] = t++;
        int num_of_children = 0;
        bool exist_articulation = false, is_multiple_edge = false;
        for (const auto &e : G[v]) {
            if (ord[e.to] == -1) {
                num_of_children++;
                t = dfs(G, t, e.to, v);
                low[v] = min(low[v], low[e.to]);  // forward edge of DFS-tree
                exist_articulation |= (p != -1) && (low[e.to] >= ord[v]);
                if (ord[v] < low[e.to]) brs.push_back(e);
            } else if (e.to != p || is_multiple_edge) {
                low[v] = min(low[v], ord[e.to]);  // back edge
            } else {
                is_multiple_edge = true;
            }
        }
        if (exist_articulation || (p == -1 && num_of_children > 1)) {
            aps.emplace_back(v);
        }
        return t;
    }

    void solve(const Graph<T> &G) {
        ord.assign(G.size(), -1), low.assign(G.size(), -1);
        for (int v = 0, k = 0; v < (int)G.size(); v++) {
            if (ord[v] == -1) k = dfs(G, k, v, -1);
        }
    }
};

// BiConnected Components decomposition
// block-cut tree (aps: 0, 1, ..., A-1, components: A, A+1, ..., A+C-1)
// (A: size of aps, C: num of components)
template<class T> struct BiConnectedComponentsDecomposition {
    // result
    LowLink<T> ll;
    vector<int> id_ap;   // index of the articulation point (size: V)
    vector<int> id_cc;   // index of the connected component (size: V)
    vector<vector<int>> groups;   // biconnected components (size: C)
    vector<vector<int>> tree;     // block-cut tree (size: A + C)

    // intermediate results
    vector<int> seen, finished;
    vector<vector<pair<int, int>>> grouped_edges;
    vector<pair<int, int>> tmp_edges;

    // constructor
    BiConnectedComponentsDecomposition() { }
    BiConnectedComponentsDecomposition(const Graph<T> &G) {
        solve(G);
    }
    void init(const Graph<T> &G) {
        solve(G);
    }

    // getter, original graph to block-cut tree (v: node of orignal graph)
    int is_ap_original_graph(int v) const {
        return (id_ap[v] != -1);
    }
    int get_id(int v) const {
        return (id_ap[v] == -1 ? id_cc[v] : id_ap[v]);
    }

    // getter, block-cut tree to orignal graph（v: node-id of block-cut tree)
    int is_ap(int v) const {
        return (v < ll.aps.size());
    }
    int get_ap(int v) const {
        if (v >= (int)ll.aps.size()) return -1;  // not ap
        else return ll.aps[v];
    }
    int get_size(int v) const {  // including aps
        if (v < (int)ll.aps.size()) return 1;  // ap
        else return groups[v - ll.aps.size()].size();
    }
    vector<int> get_group(int v) const {
        if (v < (int)ll.aps.size()) return vector<int>({ll.aps[v]});  // ap
        else return groups[v - ll.aps.size()];
    }

    // solver
    void dfs(const Graph<T> &G, int v, int p) {
        seen[v] = true;
        if (G[v].empty()) {
            groups.emplace_back(vector<int>({v}));
        }
        for (const auto &e : G[v]) {
            if (e.to == p) continue;
            if (!seen[e.to] || ll.ord[e.to] < ll.ord[v]) {
                tmp_edges.emplace_back(minmax(v, e.to));
            }
            if (!seen[e.to]) {
                dfs(G, e.to, v);
                if (ll.low[e.to] >= ll.ord[v]) {
                    groups.emplace_back(vector<int>({v}));
                    grouped_edges.emplace_back();
                    int ap = v;
                    while (!tmp_edges.empty()) {
                        const auto &e2 = tmp_edges.back();
                        if (!finished[e2.first] && e2.first != ap) {
                            groups.back().emplace_back(e2.first);
                            finished[e2.first] = true;
                        }
                        if (!finished[e2.second] && e2.second != ap) {
                            groups.back().emplace_back(e2.second);
                            finished[e2.second] = true;
                        }
                        grouped_edges.back().emplace_back(e2);
                        tmp_edges.pop_back();
                        if (e2.first == min(v, e.to) && e2.second == max(v, e.to)) break;
                    }
                }
            }
        }
    }

    void solve(const Graph<T> &G) {
        ll.init(G);
        seen.assign(G.size(), false), finished.assign(G.size(), false);
        for (int v = 0; v < (int)G.size(); v++) {
            if (!seen[v]) dfs(G, v, -1);
        }
        id_ap.assign(G.size(), -1), id_cc.assign(G.size(), -1);
        for (int i = 0; i < (int)ll.aps.size(); i++) {
            id_ap[ll.aps[i]] = i;
        }
        tree.assign(ll.aps.size() + grouped_edges.size(), vector<int>());
        vector<int> last(G.size(), -1);
        for (int i = 0; i < (int)grouped_edges.size(); i++) {
            vector<int> st;
            for (auto [u, v] : grouped_edges[i]) {
                st.push_back(u), st.push_back(v);
            }
            for (auto v : st) {
                if (id_ap[v] == -1) {
                    id_cc[v] = i + ll.aps.size();
                } else if (last[v] != i) {
                    tree[i + ll.aps.size()].push_back(id_ap[v]);
                    tree[id_ap[v]].push_back(i + ll.aps.size());
                    last[v] = i;
                }
            }
        }
    }
};


void AOJ_3022() {
    long long N, M, u, v, all = 0;
    cin >> N >> M;
    vector<long long> w(N), res(N, 0);
    for (int i = 0; i < N; i++) cin >> w[i], all += w[i];
    Graph<int> G(N);
    for (int i = 0; i < M; i++) {
        cin >> u >> v, u--, v--;
        G.add_edge(u, v), G.add_edge(v, u);
    }

    // Block-Cut 木上を形成
    BiConnectedComponentsDecomposition<int> bcc(G);

    // 関節点以外について求める
    for (int ov = 0; ov < N; ov++) {
        if (!bcc.is_ap_original_graph(ov)) res[ov] = all - w[ov];
    }

    // 関節点について求める：Block-Cut 木上の DP
    auto tree = bcc.tree;
    vector<long long> sum(tree.size(), 0);
    for (int v = 0; v < tree.size(); v++) {
        const auto &group = bcc.get_group(v);
        for (auto ov : group) sum[v] += w[ov];
    }
    auto rec = [&](auto rec, int v, int p) -> long long {
        const auto &group = bcc.get_group(v);
        long long ma = 0, all_weight = sum[v];
        for (auto ch : tree[v]) {
            if (ch == p) continue;
            long long sub = rec(rec, ch, v);
            if (bcc.is_ap(v)) sub -= sum[v];
            else sub -= sum[ch];
            ma = max(ma, sub), all_weight += sub;
        }

        // 関節点について処理する
        if (bcc.is_ap(v)) {
            int ov = bcc.get_ap(v);
            long long rem = all - all_weight;
            ma = max(ma, rem);
            res[ov] = ma;
        }
        return all_weight;
    };
    rec(rec, 0, -1);

    for (auto val : res) cout << val << endl;
}


int main() {
    AOJ_3022();
}
accuracy: 1
time_ms: 120
memory_kb: 45568
final_rank: 16

code_snippet: #include <bits/stdc++.h>
using namespace std;


#define DEBUG 1
#define COUT(x) if (DEBUG) cout << #x << " = " << (x) << " (L" << __LINE__ << ")" << endl
template<class T1, class T2> ostream& operator << (ostream &s, pair<T1,T2> P)
{ return s << '<' << P.first << ", " << P.second << '>'; }
template<class T> ostream& operator << (ostream &s, vector<T> P)
{ for (int i = 0; i < P.size(); ++i) { if (i > 0) { s << " "; } s << P[i]; } return s; }
template<class T> ostream& operator << (ostream &s, deque<T> P)
{ for (int i = 0; i < P.size(); ++i) { if (i > 0) { s << " "; } s << P[i]; } return s; }
template<class T> ostream& operator << (ostream &s, vector<vector<T> > P)
{ for (int i = 0; i < P.size(); ++i) { s << endl << P[i]; } return s << endl; }
template<class T> ostream& operator << (ostream &s, set<T> P)
{ for (auto it : P) { s << "<" << it << "> "; } return s; }
template<class T> ostream& operator << (ostream &s, multiset<T> P)
{ for (auto it : P) { s << "<" << it << "> "; } return s; }
template<class T1, class T2> ostream& operator << (ostream &s, map<T1,T2> P)
{ for (auto it : P) { s << "<" << it.first << "->" << it.second << "> "; } return s; }




// Union-Find
struct UnionFind {
    // core member
    vector<int> par, nex;

    // constructor
    UnionFind() { }
    UnionFind(int N) : par(N, -1), nex(N) {
        init(N);
    }
    void init(int N) {
        par.assign(N, -1);
        nex.resize(N);
        for (int i = 0; i < N; ++i) nex[i] = i;
    }
    
    // core methods
    int root(int x) {
        if (par[x] < 0) return x;
        else return par[x] = root(par[x]);
    }
    
    bool same(int x, int y) {
        return root(x) == root(y);
    }
    
    bool merge(int x, int y) {
        x = root(x), y = root(y);
        if (x == y) return false;
        if (par[x] > par[y]) swap(x, y); // merge technique
        par[x] += par[y];
        par[y] = x;
        swap(nex[x], nex[y]);
        return true;
    }
    
    int size(int x) {
        return -par[root(x)];
    }
    
    // get group
    vector<int> group(int x) {
        vector<int> res({x});
        while (nex[res.back()] != x) res.push_back(nex[res.back()]);
        return res;
    }
    vector<vector<int>> groups() {
        vector<vector<int>> member(par.size());
        for (int v = 0; v < (int)par.size(); ++v) {
            member[root(v)].push_back(v);
        }
        vector<vector<int>> res;
        for (int v = 0; v < (int)par.size(); ++v) {
            if (!member[v].empty()) res.push_back(member[v]);
        }
        return res;
    }
    
    // debug
    friend ostream& operator << (ostream &s, UnionFind uf) {
        const vector<vector<int>> &gs = uf.groups();
        for (const vector<int> &g : gs) {
            s << "group: ";
            for (int v : g) s << v << " ";
            s << endl;
        }
        return s;
    }
};

// Edge Class
template<class T> struct Edge {
    int from, to;
    T val;
    Edge() : from(-1), to(-1), val(-1) { }
    Edge(int f, int t, T v = -1) : from(f), to(t), val(v) {}
    friend ostream& operator << (ostream& s, const Edge& e) {
        return s << e.from << "->" << e.to;
    }
};

// graph class
template<class T> struct Graph {
    vector<vector<Edge<T>>> list;
    
    Graph() { }
    Graph(int n) : list(n) { }
    Graph(const Graph<T> &G) : list(G.list) { }
    void init(int n) {
        list.assign(n, vector<Edge<T>>());
    }
    Graph &operator = (const Graph &g) {
        list = g.list;
        return *this;
    }

    const vector<Edge<T>> &operator [] (int i) const { return list[i]; }
    const size_t size() const { return list.size(); }
    const void clear() {
        list.clear();
    }
    const void resize(int n) {
        list.resize(n);
    }

    void add_edge(int from, int to, T val = -1) {
        list[from].push_back(Edge(from, to, val));
        list[to].push_back(Edge(to, from, val));
    }

    friend ostream &operator << (ostream &s, const Graph &G) {
        s << endl;
        for (int i = 0; i < G.size(); ++i) {
            s << i << " -> ";
            for (const auto &e : G[i]) s << e.to << " ";
            s << endl;
        }
        return s;
    }
};

// low-link
template<class T> struct LowLink {
    // results
    vector<int> ord, low;
    vector<int> aps;         // articulation points
    vector<Edge<T>> brs;     // brideges

    // constructor
    LowLink() { }
    LowLink(const Graph<T> &G) {
        solve(G);
    }
    void init(const Graph<T> &G) {
        solve(G);
    }

    // solver
    int dfs(const Graph<T> &G, int t, int v, int p) {
        ord[v] = low[v] = t++;
        int num_of_children = 0;
        bool exist_articulation = false, is_multiple_edge = false;
        for (const auto &e : G[v]) {
            if (ord[e.to] == -1) {
                num_of_children++;
                t = dfs(G, t, e.to, v);
                low[v] = min(low[v], low[e.to]);  // forward edge of DFS-tree
                exist_articulation |= (p != -1) && (low[e.to] >= ord[v]);
                if (ord[v] < low[e.to]) brs.push_back(e);
            } else if (e.to != p || is_multiple_edge) {
                low[v] = min(low[v], ord[e.to]);  // back edge
            } else {
                is_multiple_edge = true;
            }
        }
        if (exist_articulation || (p == -1 && num_of_children > 1)) {
            aps.emplace_back(v);
        }
        return t;
    }

    void solve(const Graph<T> &G) {
        ord.assign(G.size(), -1), low.assign(G.size(), -1);
        for (int v = 0, k = 0; v < (int)G.size(); v++) {
            if (ord[v] == -1) k = dfs(G, k, v, -1);
        }
    }
};

// BiConnected Components decomposition
// block-cut tree (aps: 0, 1, ..., A-1, components: A, A+1, ..., A+C-1)
// (A: size of aps, C: num of components)
template<class T> struct BiConnectedComponentsDecomposition {
    // result
    LowLink<T> ll;
    vector<int> id_ap;   // index of the articulation point (size: V)
    vector<int> id_cc;   // index of the connected component (size: V)
    vector<vector<int>> groups;   // biconnected components (size: C)
    vector<vector<int>> tree;     // block-cut tree (size: A + C)

    // intermediate results
    vector<int> seen, finished;
    vector<vector<pair<int, int>>> grouped_edges;
    vector<pair<int, int>> tmp_edges;

    // constructor
    BiConnectedComponentsDecomposition() { }
    BiConnectedComponentsDecomposition(const Graph<T> &G) {
        solve(G);
    }
    void init(const Graph<T> &G) {
        solve(G);
    }

    // getter, original graph to block-cut tree (v: node of orignal graph)
    int is_ap_original_graph(int v) const {
        return (id_ap[v] != -1);
    }
    int get_id(int v) const {
        return (id_ap[v] == -1 ? id_cc[v] : id_ap[v]);
    }

    // getter, block-cut tree to orignal graph（v: node-id of block-cut tree)
    int is_ap(int v) const {
        return (v < ll.aps.size());
    }
    int get_ap(int v) const {
        if (v >= (int)ll.aps.size()) return -1;  // not ap
        else return ll.aps[v];
    }
    int get_size(int v) const {  // including aps
        if (v < (int)ll.aps.size()) return 1;  // ap
        else return groups[v - ll.aps.size()].size();
    }
    vector<int> get_group(int v) const {
        if (v < (int)ll.aps.size()) return vector<int>({ll.aps[v]});  // ap
        else return groups[v - ll.aps.size()];
    }

    // solver
    void dfs(const Graph<T> &G, int v, int p) {
        seen[v] = true;
        if (G[v].empty()) {
            groups.emplace_back(vector<int>({v}));
        }
        for (const auto &e : G[v]) {
            if (e.to == p) continue;
            if (!seen[e.to] || ll.ord[e.to] < ll.ord[v]) {
                tmp_edges.emplace_back(minmax(v, e.to));
            }
            if (!seen[e.to]) {
                dfs(G, e.to, v);
                if (ll.low[e.to] >= ll.ord[v]) {
                    groups.emplace_back(vector<int>({v}));
                    grouped_edges.emplace_back();
                    int ap = v;
                    while (!tmp_edges.empty()) {
                        const auto &e2 = tmp_edges.back();
                        if (!finished[e2.first] && e2.first != ap) {
                            groups.back().emplace_back(e2.first);
                            finished[e2.first] = true;
                        }
                        if (!finished[e2.second] && e2.second != ap) {
                            groups.back().emplace_back(e2.second);
                            finished[e2.second] = true;
                        }
                        grouped_edges.back().emplace_back(e2);
                        tmp_edges.pop_back();
                        if (e2.first == min(v, e.to) && e2.second == max(v, e.to)) break;
                    }
                }
            }
        }
    }

    void solve(const Graph<T> &G) {
        ll.init(G);
        seen.assign(G.size(), false), finished.assign(G.size(), false);
        for (int v = 0; v < (int)G.size(); v++) {
            if (!seen[v]) dfs(G, v, -1);
        }
        id_ap.assign(G.size(), -1), id_cc.assign(G.size(), -1);
        for (int i = 0; i < (int)ll.aps.size(); i++) {
            id_ap[ll.aps[i]] = i;
        }
        tree.assign(ll.aps.size() + grouped_edges.size(), vector<int>());
        vector<int> last(G.size(), -1);
        for (int i = 0; i < (int)grouped_edges.size(); i++) {
            vector<int> st;
            for (auto [u, v] : grouped_edges[i]) {
                st.push_back(u), st.push_back(v);
            }
            for (auto v : st) {
                if (id_ap[v] == -1) {
                    id_cc[v] = i + ll.aps.size();
                } else if (last[v] != i) {
                    tree[i + ll.aps.size()].push_back(id_ap[v]);
                    tree[id_ap[v]].push_back(i + ll.aps.size());
                    last[v] = i;
                }
            }
        }
    }
};

int main() {
    int N, M, u, v;
    cin >> N >> M;
    vector<long long> w(N), res(N, 0);
    for (int i = 0; i < N; i++) cin >> w[i];

    UnionFind uf(N);
    Graph<int> G(N);
    for (int i = 0; i < M; i++) {
        cin >> u >> v, u--, v--;
        G.add_edge(u, v);
        G.add_edge(v, u);
        uf.merge(u, v);
    }
    vector<long long> all_comp_sum(N, 0);
    for (int v = 0; v < N; v++) {
        int r = uf.root(v);
        all_comp_sum[r] += w[v];
    }

    // Block-Cut 木上を形成
    BiConnectedComponentsDecomposition<int> bcc(G);

    // 関節点以外について求める
    for (int ov = 0; ov < N; ov++) {
        if (!bcc.is_ap_original_graph(ov)) {
            res[ov] = all_comp_sum[uf.root(ov)] - w[ov];
        }
    }

    // 関節点について求める：Block-Cut 木上の DP
    auto tree = bcc.tree;
    vector<long long> sum(tree.size(), 0);
    for (int v = 0; v < tree.size(); v++) {
        const auto &group = bcc.get_group(v);
        for (auto ov : group) sum[v] += w[ov];

        //cout << v << ": " << group << ": " << sum[v] << endl;
    }
    vector<bool> seen(tree.size(), false);
    auto rec = [&](auto rec, int v, int p) -> long long {
        seen[v] = true;
        const auto &group = bcc.get_group(v);
        long long ma = 0, all_weight = sum[v];
        for (auto ch : tree[v]) {
            if (ch == p) continue;
            long long sub = rec(rec, ch, v);
            if (bcc.is_ap(v)) sub -= sum[v];
            else sub -= sum[ch];
            ma = max(ma, sub), all_weight += sub;
        }

        // 関節点について処理する
        if (bcc.is_ap(v)) {
            int ov = bcc.get_ap(v);
            long long rem = all_comp_sum[uf.root(ov)] - all_weight;
            ma = max(ma, rem);
            res[ov] = ma;
        }
        
        //cout << v << ": " << all_weight << endl;
        return all_weight;
    };
    for (int v = 0; v < tree.size(); v++) {
        if (seen[v]) continue;
        rec(rec, v, -1);
    }

    for (auto val : res) cout << val << endl;
}
accuracy: 1
time_ms: 120
memory_kb: 47220
final_rank: 19

code_snippet: #include <bits/stdc++.h>

using namespace std;

vector<vector<int>> adj, adj2;
vector<int> low, order;
vector<long long> val;
int timer = 0;

void dfs(int u, int p) {
    low[u] = order[u] = timer++;
    for (int &v: adj[u]) {
        if (order[v] == -1) {
            dfs(v, u);
            adj2[u].push_back(v);
            val[u] += val[v];
            low[u] = min(low[u], low[v]);
        } else if (v != p)
            low[u] = min(low[u], order[v]);

    }
}

int main() {
    int n, m;
    cin >> n >> m;
    adj.assign(n + 1, {});
    adj2.assign(n + 1, {});
    low.assign(n + 1, {});
    order.assign(n + 1, -1);
    val.assign(n + 1, -1);

    for (int u = 1; u <= n; ++u)
        cin >> val[u];

    for (int i = 0; i < m; ++i) {
        int u, v;
        cin >> u >> v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }

    dfs(1, 0);

    for (int u = 1; u <= n; ++u) {
        long long res = 0, sum = val[1] - val[u];
        for (int &v: adj2[u]) {
            if (order[u] > low[v]) sum += val[v];
            else res = max(res, val[v]);
        }
        cout << max(res, sum) << '\n';
    }
}
accuracy: 1
time_ms: 60
memory_kb: 14188
final_rank: 3

code_snippet: #include <bits/stdc++.h>

using namespace std;

vector<vector<int>> adj, adj2;
vector<int> low, val, order;
int timer = 0;

void dfs(int u, int p) {
    low[u] = order[u] = timer++;
    for (int &v: adj[u]) {
        if (order[v] == -1) {
            dfs(v, u);
            adj2[u].push_back(v);
            val[u] += val[v];
            low[u] = min(low[u], low[v]);
        } else if (v != p)
            low[u] = min(low[u], order[v]);

    }
}

int main() {
    int n, m;
    cin >> n >> m;
    adj.assign(n + 1, {});
    adj2.assign(n + 1, {});
    low.assign(n + 1, {});
    order.assign(n + 1, -1);
    val.assign(n + 1, -1);

    for (int u = 1; u <= n; ++u)
        cin >> val[u];

    for (int i = 0; i < m; ++i) {
        int u, v;
        cin >> u >> v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }

    dfs(1, 0);

    for (int u = 1; u <= n; ++u) {
        int res = 0, sum = val[1] - val[u];
        for (int &v: adj2[u]) {
            if (order[u] > low[v]) sum += val[v];
            else res = max(res, val[v]);
        }
        cout << max(res, sum) << '\n';
    }
}
accuracy: 0.3055555555555556
time_ms: 50
memory_kb: 11408
final_rank: 20

code_snippet: // #pragma GCC target("avx2")
// #pragma GCC optimize("O3")
// #pragma GCC optimize("unroll-loops")

#define CONSTANTS
#define _USE_MATH_DEFINES
#include <bits/stdc++.h>
using namespace std;

constexpr long long INF = 1e18;
// constexpr long long INF = LONG_LONG_MAX;
// constexpr int MOD = 1000000007;
constexpr int MOD = 998244353;
constexpr long double EPS = 1e-10;
constexpr long double PI = M_PI;

using ll = long long; using ull = unsigned long long; using ld = long double; using pll = pair<ll, ll>; using pii = pair<int, int>; using pli = pair<ll, int>; using pil = pair<int, ll>; template<typename T> using vv = vector<vector<T>>; using vvl = vv<ll>; using vvi = vv<int>; using vvpll = vv<pll>; using vvpli = vv<pli>; using vvpil = vv<pil>;
#define name4(i, a, b, c, d, e, ...) e
#define rep(...) name4(__VA_ARGS__, rep4, rep3, rep2, rep1)(__VA_ARGS__)
#define rep1(i, a) for (ll i = 0, _aa = a; i < _aa; i++)
#define rep2(i, a, b) for (ll i = a, _bb = b; i < _bb; i++)
#define rep3(i, a, b, c) for (ll i = a, _bb = b; (c > 0 && a <= i && i < _bb) or (c < 0 && a >= i && i > _bb); i += c)
#define rrep(i, a, b) for (ll i=(a); i>(b); i--)
#define pb push_back
#define eb emplace_back
#define mkp make_pair
#define ALL(A) begin(A), end(A)
#define UNIQUE(A) sort(ALL(A)), A.erase(unique(ALL(A)), A.end())
#define elif else if
#define tostr to_string
#ifndef CONSTANTS
constexpr ll INF = 1e18; constexpr int MOD = 1000000007; constexpr ld EPS = 1e-10; constexpr ld PI = M_PI;
#endif
template<typename T1, typename T2> istream &operator>>(istream &is, pair<T1, T2> &p) { is >> p.first >> p.second; return is; } template<typename T> istream &operator>>(istream &is, vector<T> &v) { for (T &in : v) is >> in; return is; } template<typename T = ll> vector<T> LIST(int N) { vector<T> A(N); rep(i, N) { cin >> A[i]; } return A; }
template<typename T> bool chmax(T &x, T y) { return (y > x) ? x = y, true : false; }
template<typename T1, typename T2> ostream &operator<<(ostream &os, const pair<T1, T2> &p) { return os << p.first << ' ' << p.second; } template<class T, size_t... Is> void print_tuple(ostream &os, const T &arg, index_sequence<Is...>) { static_cast<void>(((os << (Is == 0 ? "" : " "), os << get<Is>(arg)), ...)); } template<class... Ts> ostream &operator<<(ostream &os, const tuple<Ts...> &arg) { print_tuple(os, arg, make_index_sequence<sizeof...(Ts)>()); return os; } template<typename T, size_t N> ostream &operator<<(ostream &os, const array<T, N> &arr) { rep(i, N) { os << arr[i]; if (i != (int)N - 1) { os << ' '; } } return os; } template<typename T, size_t N> void print(const array<T, N> &arr, string sep = " ") { rep(i, N) { cout << arr[i]; if (i != (int)N - 1) cout << sep; } cout << '\n'; } template<typename T> ostream &operator<<(ostream &os, const vector<T> &vec) { rep(i, vec.size()) { os << vec[i]; if (i != (int)vec.size() - 1) { os << ' '; } } return os; } template<typename T> void print(const vector<T> &vec, string sep = " ") { rep(i, vec.size()) { cout << vec[i]; if (i != (int)vec.size() - 1) cout << sep; } cout << '\n'; } template<typename T> void print(const deque<T> &que, string sep = " ") { vector<T> vec(ALL(que)); print(vec, sep); } template<typename T> void print(const set<T> &se, string sep = " ") { vector<T> vec(ALL(se)); print(vec, sep); } template<typename T> void print(const initializer_list<T> &li, string sep = " ") { vector<T> V(ALL(li)); print(V, sep); } void print() { cout << '\n'; } template<typename T> void print(T out) { cout << out << '\n'; }
#define debug(...) multi_debug(#__VA_ARGS__, __VA_ARGS__)
template<typename T> void multi_debug(string name, const vv<T> &grid) { cerr << name << ":" << endl; int H = grid.size(); int W = grid[0].size(); vector<int> mxlen(W); rep(h, H) { rep(w, W) { chmax(mxlen[w], (int)tostr(grid[h][w]).size()); } } rep(h, H) { rep(w, W) { int pad = mxlen[w] - (int)tostr(grid[h][w]).size(); cerr << string(pad, ' ') << grid[h][w]; if (w == W - 1) { cerr << endl; } else { cerr << ' '; } } } } template<class Tp, class... Ts> void multi_debug(string names, Tp arg, Ts... args) { if constexpr (sizeof...(Ts) == 0) { while (names.back() == ' ') { names.pop_back(); } cerr << names << ": " << arg << endl; } else { int n = names.size(), comma_pos = -1, paren_depth = 0, inside_quote = false; rep(i, n) { if (not inside_quote and paren_depth == 0 and names[i] == ',') { comma_pos = i; break; } if (names[i] == '\"' or names[i] == '\'') { if (i > 0 and names[i - 1] == '\\') continue; inside_quote ^= true; } if (not inside_quote and names[i] == '(') { paren_depth++; } if (not inside_quote and names[i] == ')') { paren_depth--; } } assert(comma_pos != -1); string name = names.substr(0, comma_pos); while (name.back() == ' ') { name.pop_back(); } cerr << name << ": " << arg << endl; int next_begin_at = comma_pos + 1; while (names[next_begin_at] == ' ') { next_begin_at++; } names = names.substr(next_begin_at); multi_debug(names, args...); } } template<typename T> void print(const vector<T> &V, char sep) { print(V, string{sep}); } template<typename T, size_t N> void print(const array<T, N> &arr, char sep) { print(arr, string{sep}); }
template<typename T> T sum(const vector<T> &A) { return accumulate(ALL(A), (T)0); } template<typename key, typename val> val sum(const map<key, val> &mp) { val res = 0; for (auto &[k, v] : mp) res += v; return res; }

struct LowLink { const vvi &g; int N; vector<int> ord, low, articulations, is_arti; vector<pair<int, int>> bridges; LowLink(const vvi &_g) : g(_g), N(g.size()), ord(N, -1), low(N, -1), is_arti(N) { for (int i = 0, k = 0; i < N; i++) { if (ord[i] == -1) { k = dfs(i, k, -1); } } sort(ALL(bridges)); } bool is_articulation(int u) { return is_arti[u]; } bool is_bridge(int u, int v) { if (u > v) swap(u, v); auto itr = lower_bound(ALL(bridges), pii{u, v}); return itr != bridges.end() and (*itr) == pii{u, v}; } bool has_articulation() { return articulations.size(); } bool has_bridge() { return bridges.size(); } vector<int> get_articulations() { return articulations; } vector<pii> get_bridges() { return bridges; } private: int dfs(int idx, int k, int par) { low[idx] = (ord[idx] = k++); int cnt = 0; bool arti = false, second = false; for (auto &to : g[idx]) { if (ord[to] == -1) { cnt++; k = dfs(to, k, idx); low[idx] = min(low[idx], low[to]); arti |= (par != -1) && (low[to] >= ord[idx]); if (ord[idx] < low[to]) { bridges.emplace_back(minmax(idx, (int)to)); } } else if (to != par || second) { low[idx] = min(low[idx], ord[to]); } else { second = true; } } arti |= par == -1 && cnt > 1; if (arti) { articulations.push_back(idx); is_arti[idx] = true; } return k; } };
struct BiConnectedComponents : LowLink { vector<int> used; vector<vector<pair<int, int>>> bc; vector<pair<int, int>> tmp; BiConnectedComponents(const vvi &_g) : LowLink(_g) { build(); } void build() { used.assign(this->g.size(), 0); for (int i = 0; i < (int)used.size(); i++) { if (!used[i]) dfs(i, -1); } } void dfs(int idx, int par) { used[idx] = true; for (auto &to : this->g[idx]) { if (to == par) continue; if (!used[to] || this->ord[to] < this->ord[idx]) { tmp.emplace_back(minmax<int>(idx, to)); } if (!used[to]) { dfs(to, idx); if (this->low[to] >= this->ord[idx]) { bc.emplace_back(); while (true) { auto e = tmp.back(); bc.back().emplace_back(e); tmp.pop_back(); if (e.first == min<int>(idx, to) && e.second == max<int>(idx, to)) { break; } } } } } } };
struct BlockCutTree { const vector<vector<int>> g; BiConnectedComponents bcc; vector<vector<int>> aux, groups; vector<int> idar, idcc, sz, is_arti; BlockCutTree(const vector<vector<int>> &_g) : g(_g), bcc(g) { build(); } void build() { auto ar = bcc.get_articulations(); idar.resize(g.size(), -1); idcc.resize(g.size(), -1); for (int i = 0; i < (int)ar.size(); i++) idar[ar[i]] = i; aux.resize(ar.size() + bcc.bc.size()); vector<int> last(g.size(), -1); for (int i = 0; i < (int)bcc.bc.size(); i++) { vector<int> st; for (auto &[u, v] : bcc.bc[i]) st.push_back(u), st.push_back(v); for (auto &u : st) { if (idar[u] == -1) idcc[u] = i + ar.size(); else if (last[u] != i) { add(i + ar.size(), idar[u]); last[u] = i; } } } sz.resize(aux.size()); is_arti.resize(aux.size()); groups.resize(aux.size()); for (int u = 0; u < g.size(); u++) { groups[this->id(u)].eb(u); sz[this->id(u)]++; if (idar[u] != -1) { is_arti[this->id(u)] = true; } } } vector<int> &operator[](int i) { return aux[i]; } int size() const { return aux.size(); } int size(int k) { return sz[k]; } int id(int i) { return idar[i] == -1 ? idcc[i] : idar[i]; } bool is_articulation(int k) { return is_arti[k]; } vector<vector<int>> get_nodes() { return aux; } vector<vector<int>> get_groups() { return groups; } private: void add(int i, int j) { if (i == -1 or j == -1) return; aux[i].push_back(j); aux[j].push_back(i); }; };

void solve() {
    ll N, M;
    cin >> N >> M;
    vector<ll> W(N);
    cin >> W;
    vvi nodes(N);
    rep(i, M) {
        int u, v;
        cin >> u >> v;
        u--, v--;
        nodes[u].eb(v);
        nodes[v].eb(u);
    }

    BlockCutTree bct(nodes);
    ll K = bct.size();
    vector<ll> W2(K);
    rep(u, N) {
        W2[bct.id(u)] += W[u];
    }
    ll wsm = sum(W);
    vector<ll> dp(K), ans(N, wsm);
    rep(u, N) {
        ans[u] -= W[u];
    }
    auto groups = bct.get_groups();
    auto dfs = [&](auto &&f, ll u, ll prv) -> void {
        dp[u] = W2[u];
        for (auto v : bct[u]) {
            if (v == prv) continue;
            f(f, v, u);
            dp[u] += dp[v];
        }
        if (bct.is_articulation(u)) {
            ll mx = wsm - dp[u];
            for (auto v : bct[u]) {
                if (v == prv) continue;
                chmax(mx, dp[v]);
            }
            assert(groups[u].size() == 1);
            ans[groups[u][0]] = mx;
        }
    };
    dfs(dfs, 0, -1);
    print(ans, "\n");
}

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(15);

    // single test case
    solve();

    // multi test cases
    // int T;
    // cin >> T;
    // while (T--) solve();

    return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 50212
final_rank: 15

code_snippet: // #pragma GCC target("avx2")
// #pragma GCC optimize("O3")
// #pragma GCC optimize("unroll-loops")

#define CONSTANTS
#define _USE_MATH_DEFINES
#include <bits/stdc++.h>
using namespace std;

constexpr long long INF = 1e18;
// constexpr long long INF = LONG_LONG_MAX;
// constexpr int MOD = 1000000007;
constexpr int MOD = 998244353;
constexpr long double EPS = 1e-10;
constexpr long double PI = M_PI;

using ll = long long; using ull = unsigned long long; using ld = long double; using pll = pair<ll, ll>; using pii = pair<int, int>; using pli = pair<ll, int>; using pil = pair<int, ll>; template<typename T> using vv = vector<vector<T>>; using vvl = vv<ll>; using vvi = vv<int>; using vvpll = vv<pll>; using vvpli = vv<pli>; using vvpil = vv<pil>;
#define name4(i, a, b, c, d, e, ...) e
#define rep(...) name4(__VA_ARGS__, rep4, rep3, rep2, rep1)(__VA_ARGS__)
#define rep1(i, a) for (ll i = 0, _aa = a; i < _aa; i++)
#define rep2(i, a, b) for (ll i = a, _bb = b; i < _bb; i++)
#define rep3(i, a, b, c) for (ll i = a, _bb = b; (c > 0 && a <= i && i < _bb) or (c < 0 && a >= i && i > _bb); i += c)
#define rrep(i, a, b) for (ll i=(a); i>(b); i--)
#define pb push_back
#define eb emplace_back
#define mkp make_pair
#define ALL(A) begin(A), end(A)
#define UNIQUE(A) sort(ALL(A)), A.erase(unique(ALL(A)), A.end())
#define elif else if
#define tostr to_string
#ifndef CONSTANTS
constexpr ll INF = 1e18; constexpr int MOD = 1000000007; constexpr ld EPS = 1e-10; constexpr ld PI = M_PI;
#endif
template<typename T1, typename T2> istream &operator>>(istream &is, pair<T1, T2> &p) { is >> p.first >> p.second; return is; } template<typename T> istream &operator>>(istream &is, vector<T> &v) { for (T &in : v) is >> in; return is; } template<typename T = ll> vector<T> LIST(int N) { vector<T> A(N); rep(i, N) { cin >> A[i]; } return A; }
template<typename T> bool chmax(T &x, T y) { return (y > x) ? x = y, true : false; }
template<typename T1, typename T2> ostream &operator<<(ostream &os, const pair<T1, T2> &p) { return os << p.first << ' ' << p.second; } template<class T, size_t... Is> void print_tuple(ostream &os, const T &arg, index_sequence<Is...>) { static_cast<void>(((os << (Is == 0 ? "" : " "), os << get<Is>(arg)), ...)); } template<class... Ts> ostream &operator<<(ostream &os, const tuple<Ts...> &arg) { print_tuple(os, arg, make_index_sequence<sizeof...(Ts)>()); return os; } template<typename T, size_t N> ostream &operator<<(ostream &os, const array<T, N> &arr) { rep(i, N) { os << arr[i]; if (i != (int)N - 1) { os << ' '; } } return os; } template<typename T, size_t N> void print(const array<T, N> &arr, string sep = " ") { rep(i, N) { cout << arr[i]; if (i != (int)N - 1) cout << sep; } cout << '\n'; } template<typename T> ostream &operator<<(ostream &os, const vector<T> &vec) { rep(i, vec.size()) { os << vec[i]; if (i != (int)vec.size() - 1) { os << ' '; } } return os; } template<typename T> void print(const vector<T> &vec, string sep = " ") { rep(i, vec.size()) { cout << vec[i]; if (i != (int)vec.size() - 1) cout << sep; } cout << '\n'; } template<typename T> void print(const deque<T> &que, string sep = " ") { vector<T> vec(ALL(que)); print(vec, sep); } template<typename T> void print(const set<T> &se, string sep = " ") { vector<T> vec(ALL(se)); print(vec, sep); } template<typename T> void print(const initializer_list<T> &li, string sep = " ") { vector<T> V(ALL(li)); print(V, sep); } void print() { cout << '\n'; } template<typename T> void print(T out) { cout << out << '\n'; }
#define debug(...) multi_debug(#__VA_ARGS__, __VA_ARGS__)
template<typename T> void multi_debug(string name, const vv<T> &grid) { cerr << name << ":" << endl; int H = grid.size(); int W = grid[0].size(); vector<int> mxlen(W); rep(h, H) { rep(w, W) { chmax(mxlen[w], (int)tostr(grid[h][w]).size()); } } rep(h, H) { rep(w, W) { int pad = mxlen[w] - (int)tostr(grid[h][w]).size(); cerr << string(pad, ' ') << grid[h][w]; if (w == W - 1) { cerr << endl; } else { cerr << ' '; } } } } template<class Tp, class... Ts> void multi_debug(string names, Tp arg, Ts... args) { if constexpr (sizeof...(Ts) == 0) { while (names.back() == ' ') { names.pop_back(); } cerr << names << ": " << arg << endl; } else { int n = names.size(), comma_pos = -1, paren_depth = 0, inside_quote = false; rep(i, n) { if (not inside_quote and paren_depth == 0 and names[i] == ',') { comma_pos = i; break; } if (names[i] == '\"' or names[i] == '\'') { if (i > 0 and names[i - 1] == '\\') continue; inside_quote ^= true; } if (not inside_quote and names[i] == '(') { paren_depth++; } if (not inside_quote and names[i] == ')') { paren_depth--; } } assert(comma_pos != -1); string name = names.substr(0, comma_pos); while (name.back() == ' ') { name.pop_back(); } cerr << name << ": " << arg << endl; int next_begin_at = comma_pos + 1; while (names[next_begin_at] == ' ') { next_begin_at++; } names = names.substr(next_begin_at); multi_debug(names, args...); } } template<typename T> void print(const vector<T> &V, char sep) { print(V, string{sep}); } template<typename T, size_t N> void print(const array<T, N> &arr, char sep) { print(arr, string{sep}); }
template<typename T> T sum(const vector<T> &A) { return accumulate(ALL(A), (T)0); } template<typename key, typename val> val sum(const map<key, val> &mp) { val res = 0; for (auto &[k, v] : mp) res += v; return res; }

struct LowLink { const vvi &g; int N; vector<int> ord, low, articulations, is_arti; vector<pair<int, int>> bridges; LowLink(const vvi &_g) : g(_g), N(g.size()), ord(N, -1), low(N, -1), is_arti(N) { for (int i = 0, k = 0; i < N; i++) { if (ord[i] == -1) { k = dfs(i, k, -1); } } sort(ALL(bridges)); } bool is_articulation(int u) { return is_arti[u]; } bool is_bridge(int u, int v) { if (u > v) swap(u, v); auto itr = lower_bound(ALL(bridges), pii{u, v}); return itr != bridges.end() and (*itr) == pii{u, v}; } bool has_articulation() { return articulations.size(); } bool has_bridge() { return bridges.size(); } vector<int> get_articulations() { return articulations; } vector<pii> get_bridges() { return bridges; } private: int dfs(int idx, int k, int par) { low[idx] = (ord[idx] = k++); int cnt = 0; bool arti = false, second = false; for (auto &to : g[idx]) { if (ord[to] == -1) { cnt++; k = dfs(to, k, idx); low[idx] = min(low[idx], low[to]); arti |= (par != -1) && (low[to] >= ord[idx]); if (ord[idx] < low[to]) { bridges.emplace_back(minmax(idx, (int)to)); } } else if (to != par || second) { low[idx] = min(low[idx], ord[to]); } else { second = true; } } arti |= par == -1 && cnt > 1; if (arti) { articulations.push_back(idx); is_arti[idx] = true; } return k; } };

// see: https://nyaannyaan.github.io/library/graph/biconnected-components.hpp
struct BiConnectedComponents : LowLink {
    vector<int> used;
    vector<vector<pair<int, int>>> bc;
    vector<pair<int, int>> tmp;

    BiConnectedComponents(const vvi &_g) : LowLink(_g) {
        build();
    }

    void build() {
        used.assign(this->g.size(), 0);
        for (int i = 0; i < (int)used.size(); i++) {
            if (!used[i]) dfs(i, -1);
        }
    }

    void dfs(int idx, int par) {
        used[idx] = true;
        for (auto &to : this->g[idx]) {
            if (to == par) continue;
            if (!used[to] || this->ord[to] < this->ord[idx]) {
                tmp.emplace_back(minmax<int>(idx, to));
            }
            if (!used[to]) {
                dfs(to, idx);
                if (this->low[to] >= this->ord[idx]) {
                    bc.emplace_back();
                    while (true) {
                        auto e = tmp.back();
                        bc.back().emplace_back(e);
                        tmp.pop_back();
                        if (e.first == min<int>(idx, to) &&
                            e.second == max<int>(idx, to)) {
                            break;
                        }
                    }
                }
            }
        }
    }
};

// see: https://nyaannyaan.github.io/library/tree/block-cut-tree.hpp
struct BlockCutTree {
    const vvi g;
    BiConnectedComponents bcc;
    vector<vector<int>> aux, groups;
    vector<int> idar, idcc, sz, is_arti;

    BlockCutTree(const vvi &_g) : g(_g), bcc(g) {
        build();
    }

    void build() {
        auto ar = bcc.get_articulations();
        idar.resize(g.size(), -1);
        idcc.resize(g.size(), -1);
        for (int i = 0; i < (int)ar.size(); i++) idar[ar[i]] = i;

        aux.resize(ar.size() + bcc.bc.size());
        vector<int> last(g.size(), -1);
        for (int i = 0; i < (int)bcc.bc.size(); i++) {
            vector<int> st;
            for (auto &[u, v] : bcc.bc[i]) st.push_back(u), st.push_back(v);
            for (auto &u : st) {
                if (idar[u] == -1) idcc[u] = i + ar.size();
                else if (last[u] != i) {
                    add(i + ar.size(), idar[u]);
                    last[u] = i;
                }
            }
        }

        sz.resize(aux.size());
        is_arti.resize(aux.size());
        groups.resize(aux.size());
        for (int u = 0; u < g.size(); u++) {
            groups[this->id(u)].eb(u);
            sz[this->id(u)]++;
            if (idar[u] != -1) {
                is_arti[this->id(u)] = true;
            }
        }
    }

    vector<int> &operator[](int i) {
        return aux[i];
    }

    // 連結成分数(縮約後グラフの頂点数)
    int size() const {
        return aux.size();
    }

    // (縮約後グラフの)頂点kの連結成分要素数
    int size(int k) {
        return sz[k];
    }

    int id(int i) {
        return idar[i] == -1 ? idcc[i] : idar[i];
    }

    // (縮約後グラフの)頂点kが元グラフで関節点かどうか
    bool is_articulation(int k) {
        return is_arti[k];
    }

    // bool is_arti(int i) {
    //     return idar[i] != -1;
    // }

    int arti() {
        return bcc.get_articulations().size();
    }

    // 縮約後グラフの隣接リスト
    vvi get_nodes() {
        return aux;
    }

    // ACLのSCCが返すみたいな各連結成分を表す隣接リスト
    vvi get_groups() {
        return groups;
    }

private:
    void add(int i, int j) {
        if (i == -1 or j == -1) return;
        aux[i].push_back(j);
        aux[j].push_back(i);
    };
};

void solve() {
    ll N, M;
    cin >> N >> M;
    vector<ll> W(N);
    cin >> W;
    vvi nodes(N);
    rep(i, M) {
        int u, v;
        cin >> u >> v;
        u--, v--;
        nodes[u].eb(v);
        nodes[v].eb(u);
    }

    BlockCutTree bct(nodes);
    ll K = bct.size();
    vector<ll> W2(K);
    rep(u, N) {
        W2[bct.id(u)] += W[u];
    }
    ll wsm = sum(W);
    vector<ll> dp(K), ans(N, wsm);
    rep(u, N) {
        ans[u] -= W[u];
    }
    auto groups = bct.get_groups();
    auto dfs = [&](auto &&f, ll u, ll prv) -> void {
        dp[u] += W2[u];
        for (auto v : bct[u]) {
            if (v == prv) continue;
            f(f, v, u);
            dp[u] += dp[v];
        }
        if (bct.is_articulation(u)) {
            ll mx = wsm - dp[u];
            for (auto v : bct[u]) {
                if (v == prv) continue;
                chmax(mx, dp[v]);
            }
            assert(groups[u].size() == 1);
            ans[groups[u][0]] = mx;
        }
    };
    dfs(dfs, 0, -1);
    print(ans, "\n");
}

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(15);

    // single test case
    solve();

    // multi test cases
    // int T;
    // cin >> T;
    // while (T--) solve();

    return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 50004
final_rank: 14

code_snippet: #line 2 "cp-library/src/cp-template.hpp"
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using uint = unsigned int;
using ull  = unsigned long long;
using i32 = int;
using u32 = unsigned int;
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128_t;
template < class T > bool chmin(T& a, T b) { if(a > b) { a = b; return true; } return false; }
template < class T > bool chmax(T& a, T b) { if(a < b) { a = b; return true; } return false; }
template < class T, class U > T ceil (T x, U y) { return (x > 0 ? (x + y - 1) / y :           x / y); }
template < class T, class U > T floor(T x, U y) { return (x > 0 ?           x / y : (x - y + 1) / y); }
int popcnt(i32 x) { return __builtin_popcount(x); }
int popcnt(u32 x) { return __builtin_popcount(x); }
int popcnt(i64 x) { return __builtin_popcountll(x); }
int popcnt(u64 x) { return __builtin_popcountll(x); }

#line 2 "cp-library/src/utility/rep_itr.hpp"
template < class T > struct itr_rep {
    T i, d;
    constexpr itr_rep(const T i) noexcept : i(i), d(1) {}
    constexpr itr_rep(const T i, const T d) noexcept : i(i), d(d) {}
    void operator++() noexcept { i += d; }
    constexpr int operator*() const noexcept { return i; }
    constexpr bool operator!=(const itr_rep x) const noexcept { return d > 0 ? i < x.i : i > x.i; }
};

template < class T > struct rep {
    const itr_rep< T > s, t;
    constexpr rep(const T t) noexcept : s(0), t(t) {}
    constexpr rep(const T s, const T t) noexcept : s(s), t(t) {}
    constexpr rep(const T s, const T t, const T d) noexcept : s(s, d), t(t, d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};

template < class T > struct revrep {
    const itr_rep < T > s, t;
    constexpr revrep(const T t) noexcept : s(t - 1, -1), t(-1, -1) {}
    constexpr revrep(const T s, const T t) noexcept : s(t - 1, -1), t(s - 1, -1) {}
    constexpr revrep(const T s, const T t, const T d) noexcept : s(t - 1, -d), t(s - 1, -d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};
#line 3 "cp-library/src/utility/io.hpp"

/* 128bit integer */
istream& operator>>(istream& is, i128& x) {
    std::string s; is >> s;
    int pm = (s[0] == '-');
    x = 0;
    for(int i : rep(pm, int(s.size()))) x = x * 10 + (s[i] - '0');
    if(pm) x *= -1;
    return is;
}
ostream& operator<<(ostream& os, const i128& x) {
    if(x == 0) return os << '0';
    i128 y = x;
    if(y < 0) {
        os << '-';
        y *= -1;
    }
    std::vector<int> ny;
    while(y > 0) {
        ny.push_back(y % 10);
        y /= 10;
    }
    for(int i : revrep(ny.size())) os << ny[i];
    return os;
}

namespace scanner {
    struct sca {
        template < class T > operator T() {
            T s; std::cin >> s; return s;
        }
    };
    struct vec {
        int n;
        vec(int n) : n(n) {}
        template < class T > operator std::vector< T >() {
            std::vector< T > v(n);
            for(T& x : v) std::cin >> x;
            return v;
        }
    };
    struct mat {
        int h, w;
        mat(int h, int w) : h(h), w(w) {}
        template < class T > operator std::vector< std::vector< T > >() {
            std::vector m(h, std::vector< T >(w));
            for(std::vector< T >& v : m) for(T& x : v) std::cin >> x;
            return m;
        }
    };
    struct speedup {
        speedup() {
            std::cin.tie(0);
            std::ios::sync_with_stdio(0);
        }
    } speedup_instance;
}
scanner::sca in() { return scanner::sca(); }
scanner::vec in(int n) { return scanner::vec(n); }
scanner::mat in(int h, int w) { return scanner::mat(h, w); }

namespace printer {
    void precision(int d) { std::cout << std::fixed << std::setprecision(d); }
    void flush() { std::cout.flush(); }
}

template < class T >
ostream& operator<<(ostream& os, const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) { os << a[i]; if(i != n - 1) os << ' '; }
    return os;
}

int print() { std::cout << '\n'; return 0; }
template < class head, class... tail > int print(head&& h, tail&&... t) {
    std::cout << h; if(sizeof...(tail)) std::cout << ' ';
    return print(std::forward<tail>(t)...);
}
template < class T > int print_n(const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) std::cout << a[i] << "\n";
    return 0;
}


#line 2 "cp-library/src/utility/key_val.hpp"

template < class K, class V >
struct key_val {
    K key; V val;
    key_val() {}
    key_val(K key, V val) : key(key), val(val) {}
    template < std::size_t Index >
    std::tuple_element_t< Index, key_val >& get() {
        if constexpr (Index == 0) return key;
        if constexpr (Index == 1) return val;
    }
};

namespace std {

template < class K, class V > struct tuple_size < key_val< K, V > > : integral_constant< size_t, 2 > {};
template < class K, class V > struct tuple_element < 0, key_val< K, V > > { using type = K; };
template < class K, class V > struct tuple_element < 1, key_val< K, V > > { using type = V; };

}
#line 2 "cp-library/src/utility/vec_op.hpp"
template < class T > key_val< int, T > max_of(const vector< T >& a) {
    int i = std::max_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class T > key_val< int, T > min_of(const vector< T >& a) {
    int i = std::min_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class S, class T > S sum_of(const vector< T >& a) {
    S sum = 0;
    for(const T x : a) sum += x;
    return sum;
}
template < class S, class T > vector< S > freq_of(const vector< T >& a, T L, T R) {
    vector< S > res(R - L, S(0));
    for(const T x : a) res[x - L] += 1;
    return res;
}
template < class S, class T > struct prefix_sum {
    vector< S > s;
    prefix_sum(const vector< T >& a) : s(a) {
        s.insert(s.begin(), S(0));
        for(int i : rep(a.size())) s[i + 1] += s[i];
    }
    // [L, R)
    S sum(int L, int R) { return s[R] - s[L]; }
};
#line 3 "cp-library/src/utility/heap.hpp"

template < class T > using heap_min = std::priority_queue< T, std::vector< T >, std::greater< T > >;
template < class T > using heap_max = std::priority_queue< T, std::vector< T >, std::less< T > >;

#line 27 "cp-library/src/cp-template.hpp"

#line 1 "cp-library/src/algorithm/bin_search.hpp"
template < class T, class F >
T bin_search(T ok, T ng, F f) {
    while(abs(ok - ng) > 1) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}

template < class T, class F >
T bin_search_real(T ok, T ng, F f, int step = 80) {
    while(step--) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}
#line 2 "cp-library/src/algorithm/argsort.hpp"

template < class T > std::vector< int > argsort(const std::vector< T > &a) {
    std::vector< int > ids((int)a.size());
    std::iota(ids.begin(), ids.end(), 0);
    std::sort(ids.begin(), ids.end(), [&](int i, int j) {
        return a[i] < a[j] || (a[i] == a[j] && i < j);
    });
    return ids;
}
#line 2 "A.cpp"

struct lowlink {
    using size_t = std::size_t;
    std::vector<std::vector<std::pair<size_t, size_t>>> graph;
    std::vector<size_t> ord, low, articulation;
    std::vector<std::pair<size_t, size_t>> bridge;

    explicit lowlink(const size_t n) : graph(n), ord(n, 0), low(n, 0) {}

    void add_edge(const size_t u, const size_t v, const size_t i) {
        assert(u < graph.size());
        assert(v < graph.size());
        graph[u].push_back({v, i});
        graph[v].push_back({u, i});
    }

    virtual void build() {
        size_t t = 0;
        std::vector<bool> used(graph.size(), false);
        std::function<void(size_t,size_t)> dfs = [&](size_t v, size_t p) -> void {
            used[v] = true;
            ord[v] = low[v] = t++;

            bool is_articulation = false, parent_checked = false;
            size_t child_cnt = 0;
            for(auto [to, _] : graph[v]) {
                if(to == p and not std::exchange(parent_checked, true)) continue;
                if(not used[to]) {
                    child_cnt++;
                    dfs(to, v);
                    low[v] = std::min(low[v], low[to]);
                    is_articulation |= p != -1 and ord[v] <= low[to];
                    if(ord[v] < low[to]) bridge.push_back(std::minmax({v, to}));
                } else {
                    low[v] = std::min(low[v], ord[to]);
                }
            }

            is_articulation |= p == -1 and child_cnt >= 2;
            if(is_articulation) articulation.push_back(v);
        };
        for(size_t v = 0; v < graph.size(); v++) if(not used[v]) dfs(v, -1);
    }
};

struct two_edge_connected_components : lowlink {
    using lowlink::lowlink;
    using lowlink::graph;
    using lowlink::ord;
    using lowlink::low;
    using lowlink::bridge;

    using size_t = std::size_t;
    std::vector<size_t> id;
    std::vector<std::vector<size_t>> group, tree;

    explicit two_edge_connected_components(const size_t n) : lowlink(n), id(n, -1) {}

    void build() override {
        lowlink::build();

        size_t c = 0;
        function<void(size_t,size_t)> dfs = [&](size_t v, size_t p) -> void {
            id[v] = (p != -1 and low[v] <= ord[p] ? id[p] : c++);
            for(auto [to, _] : graph[v]) if(id[to] == -1) dfs(to, v);
        };
        for(size_t i = 0; i < graph.size(); i++) if(id[i] == -1) dfs(i, -1);

        group.resize(c);
        for(size_t i = 0; i < graph.size(); i++) group[id[i]].push_back(i);

        tree.resize(c);
        for(auto [u, v] : bridge) {
            u = id[u], v = id[v];
            tree[u].push_back(v);
            tree[v].push_back(u);
        }
    }
};

struct biconnected_components : lowlink {
    using lowlink::lowlink;
    using lowlink::graph;
    using lowlink::ord;
    using lowlink::low;
    using size_t = std::size_t;
    std::vector<std::vector<std::tuple<size_t, size_t, size_t>>> bc;

    void build() override {
        lowlink::build();
        std::vector<bool> used(graph.size(), false);
        std::vector<std::tuple<size_t, size_t, size_t>> tmp;

        function<void(size_t,size_t)> dfs = [&](size_t v, size_t p) -> void {
            used[v] = true;
            bool parent_checked = false;
            for(auto [to, i] : graph[v]) {
                if(to == p and not exchange(parent_checked, true)) continue;
                if(not used[to] or ord[to] < ord[v]) tmp.emplace_back(v, to, i);
                if(not used[to]) {
                    dfs(to, v);
                    if(ord[v] <= low[to]) {
                        std::vector<std::tuple<size_t, size_t, size_t>> c;
                        while(true) {
                            auto e = tmp.back(); tmp.pop_back();
                            c.emplace_back(e);
                            if(get<2>(e) == i) break;
                        }
                        bc.emplace_back(std::move(c));
                    }
                }
            }
        };

        for(size_t i = 0; i < graph.size(); i++) if(not used[i]) dfs(i, -1);
    }
};

struct block_cut_tree : biconnected_components {
    using biconnected_components::biconnected_components;
    using biconnected_components::graph;
    using biconnected_components::articulation;
    using biconnected_components::bc;

    using size_t = std::size_t;
    std::vector<int> rev;
    std::vector<std::vector<size_t>> group, tree;

    explicit block_cut_tree(const size_t n) : biconnected_components(n), rev(n, -1) {}

    void build() override {
        biconnected_components::build();

        size_t c = bc.size();
        for(size_t v : articulation) rev[v] = c++;
        std::vector<size_t> last(c, -1);
        tree.resize(c);
        for(size_t i = 0; i < bc.size(); i++) {
            for(auto [u, v, _] : bc[i]) {
                for(size_t x : {u, v}) {
                    if(rev[x] != -1 and bc.size() <= rev[x]) {
                        if(std::exchange(last[rev[x]], i) != i) {
                            tree[rev[x]].push_back(i);
                            tree[i].push_back(rev[x]);
                        }
                    } else {
                        rev[x] = i;
                    }
                }
            }
        }
        group.resize(c);
        for(size_t i = 0; i < graph.size(); i++) group[rev[i]].push_back(i);
    }
};

int main() {
    int N = in(), M = in();
    vector<int> A = in(N);
    block_cut_tree bct(N);
    for(int i : rep(M)) {
        int u = in(), v = in(); u--, v--;
        bct.add_edge(u, v, i);
    }
    bct.build();
    vector<i64> w(bct.tree.size());
    for(int i : rep(N)) w[bct.rev[i]] += A[i];
    i64 SUM = sum_of<i64>(A);
    vector<i64> ans(N, SUM);
    for(int i : rep(N)) ans[i] -= A[i];

    function<i64(int,int)> dfs = [&](int v, int p) -> i64 {
        i64 max_ = 0, sum = 0;
        for(size_t to : bct.tree[v]) {
            if(to != p) {
                i64 x = dfs(to, v);
                sum += x;
                chmax(max_, x);
            }
        }
        if(bct.bc.size() <= v) ans[bct.group[v][0]] = max(SUM - sum - w[v], max_);
        return sum + w[v];
    };

    dfs(0, -1);
    print_n(ans);
}
accuracy: 1
time_ms: 70
memory_kb: 39092
final_rank: 13

code_snippet: #line 1 ".lib/template.hpp"


#include <iostream>
#include <string>
#include <vector>
#include <array>
#include <tuple>
#include <stack>
#include <queue>
#include <deque>
#include <algorithm>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <bitset>
#include <cmath>
#include <functional>
#include <cassert>
#include <climits>
#include <iomanip>
#include <numeric>
#include <memory>
#include <random>
#define allof(obj) (obj).begin(), (obj).end()
#define range(i, l, r) for(int i=l;i<r;i++)
#define bit_subset(i, S) for(int i=S, zero_cnt=0;(zero_cnt+=i==S)<2;i=(i-1)&S)
#define bit_kpop(i, n, k) for(int i=(1<<k)-1,x_bit,y_bit;i<(1<<n);x_bit=(i&-i),y_bit=i+x_bit,i=(!i?(1<<n):((i&~y_bit)/x_bit>>1)|y_bit))
#define bit_kth(i, k) ((i >> k)&1)
#define bit_highest(i) (i?63-__builtin_clzll(i):-1)
#define bit_lowest(i) (i?__builtin_ctzll(i):-1)
using ll = long long;
using ld = long double;
using ul = uint64_t;
using pi = std::pair<int, int>;
using pl = std::pair<ll, ll>;
using namespace std;

template<typename F, typename S>
std::ostream &operator<<(std::ostream &dest, const std::pair<F, S> &p){
  dest << p.first << ' ' << p.second;
  return dest;
}
template<typename T>
std::ostream &operator<<(std::ostream &dest, const std::vector<std::vector<T>> &v){
  int sz = v.size();
  if(sz==0) return dest;
  for(int i=0;i<sz;i++){
    int m = v[i].size();
    for(int j=0;j<m;j++) dest << v[i][j] << (i!=sz-1&&j==m-1?'\n':' ');
  }
  return dest;
}
template<typename T>
std::ostream &operator<<(std::ostream &dest, const std::vector<T> &v){
  int sz = v.size();
  if(sz==0) return dest;
  for(int i=0;i<sz-1;i++) dest << v[i] << ' ';
  dest << v[sz-1];
  return dest;
}
template<typename T, size_t sz>
std::ostream &operator<<(std::ostream &dest, const std::array<T, sz> &v){
  if(sz==0) return dest;
  for(int i=0;i<sz-1;i++) dest << v[i] << ' ';
  dest << v[sz-1];
  return dest;
}
template<typename T>
std::ostream &operator<<(std::ostream &dest, const std::set<T> &v){
  for(auto itr=v.begin();itr!=v.end();){
    dest << *itr;
    itr++;
    if(itr!=v.end()) dest << ' ';
  }
  return dest;
}
template<typename T, typename E>
std::ostream &operator<<(std::ostream &dest, const std::map<T, E> &v){
  for(auto itr=v.begin();itr!=v.end();){
    dest << '(' << itr->first << ", " << itr->second << ')';
    itr++;
    if(itr!=v.end()) dest << '\n';
  }
  return dest;
}
template<typename T>
vector<T> make_vec(size_t sz, T val){return std::vector<T>(sz, val);}
template<typename T, typename... Tail>
auto make_vec(size_t sz, Tail ...tail){
  return std::vector<decltype(make_vec<T>(tail...))>(sz, make_vec<T>(tail...));
}
template<typename T>
vector<T> read_vec(size_t sz){
  std::vector<T> v(sz);
  for(int i=0;i<(int)sz;i++) std::cin >> v[i];
  return v;
}
template<typename T, typename... Tail>
auto read_vec(size_t sz, Tail ...tail){
  auto v = std::vector<decltype(read_vec<T>(tail...))>(sz);
  for(int i=0;i<(int)sz;i++) v[i] = read_vec<T>(tail...);
  return v;
}
void io_init(){
  std::cin.tie(nullptr);
  std::ios::sync_with_stdio(false);
}

#line 1 ".lib/graph/graph_algorithm.hpp"


#line 1 ".lib/graph/edge.hpp"


/*
template<typename edge_weight>
struct edge_base{
  using weight = edge_weight;
  int to();
  int from();
  int id();
  weight wei();
  static weight z();
  edge_base<weight> reverse();
};
*/

template<typename edge_weight>
struct simple_edge{
  using weight = edge_weight;
  int s, t;
  simple_edge(): s(-1), t(-1){}
  simple_edge(int a, int b): s(a), t(b){}
  int to(){return t;}
  int from(){return s;}
  int id(){return -1;}
  weight wei(){return 1;}
  static weight z(){return 0;}
  simple_edge<weight> reverse(){return simple_edge<weight>{t, s};}
};

template<typename edge_weight>
struct weighted_edge{
  using weight = edge_weight;
  int s, t;
  weight w;
  weighted_edge(): s(-1), t(-1), w(0){}
  weighted_edge(int a, int b, weight c): s(a), t(b), w(c){}
  int to(){return t;}
  int from(){return s;}
  int id(){return -1;}
  weight wei(){return w;}
  static weight z(){return 0;}
  weighted_edge<weight> reverse(){return weighted_edge<weight>{t, s, w};}
};

template<typename edge_weight>
struct labeled_edge{
  using weight = edge_weight;
  int s, t, i;
  labeled_edge(): s(-1), t(-1), i(-1){}
  labeled_edge(int a, int b, int i): s(a), t(b), i(i){}
  int to(){return t;}
  int from(){return s;}
  int id(){return i;}
  weight wei(){return 1;}
  static weight z(){return 0;}
  labeled_edge<weight> reverse(){return labeled_edge<weight>{t, s, i};}
};

template<typename edge_weight>
struct weighted_labeled_edge{
  using weight = edge_weight;
  int s, t;
  weight w;
  int i;
  weighted_labeled_edge(): s(-1), t(-1), i(-1), w(0){}
  weighted_labeled_edge(int a, int b, weight w, int i): s(a), t(b), w(w), i(i){}
  int to(){return t;}
  int from(){return s;}
  int id(){return i;}
  weight wei(){return w;}
  static weight z(){return 0;}
  weighted_labeled_edge<weight> reverse(){return weighted_labeled_edge<weight>{t, s, w, i};}
};

#line 8 ".lib/graph/graph_algorithm.hpp"

namespace graph_algorithm{
  template<typename T>
  using vec = std::vector<T>;
  // O(V + E)
  // 辺の重みが1
  template<typename edge>
  struct bfs_shortest_path{
  private:
    using weight = typename edge::weight;
    using dist_p = std::pair<weight, int>;
    vec<vec<edge>> &g;
  public:
    bfs_shortest_path(vec<vec<edge>> &g): g(g){}
    static constexpr weight inf = std::numeric_limits<weight>::max() / 2;
    static constexpr weight minf = std::numeric_limits<weight>::min() / 2;
    vec<weight> dist;
    vec<edge> par;
    void build(int s){
      int n = g.size();
      if(dist.empty()){
        dist.resize(n, inf);
        par.resize(n, edge{});
      }else{
        std::fill(dist.begin(), dist.end(), inf);
        std::fill(par.begin(), par.end(), edge{});
      }
      std::queue<dist_p> que;
      dist[s] = edge::z();
      que.push(dist_p(edge::z(), s));
      while(!que.empty()){
        auto [w, v] = que.top();
        que.pop();
        if(dist[v] < w) continue;
        for(edge &e: g[v]){
          assert(e.wei() == 1);
          weight d = dist[v] + e.wei();
          int to = e.to();
          if(dist[to] > d){
            dist[to] = d;
            par[to] = e;
            que.push(dist_p(d, to));
          }
        }
      }
    }
    vec<edge> get_path(int v){
      assert(!dist.empty());
      vec<edge> ret;
      while(par[v].from() != -1) ret.push_back(par[v]), v = par[v].from();
      std::reverse(ret.begin(), ret.end());
      return ret;
    }
    weight operator [](int v){return dist[v];}
  };

  // O(V + E)
  // 辺の重みが0か1
  template<typename edge>
  struct zero_one_bfs_shortest_path{
  private:
    using weight = typename edge::weight;
    using dist_p = std::pair<weight, int>;
    vec<vec<edge>> &g;
  public:
    zero_one_bfs_shortest_path(vec<vec<edge>> &g): g(g){}
    static constexpr weight inf = std::numeric_limits<weight>::max() / 2;
    static constexpr weight minf = std::numeric_limits<weight>::min() / 2;
    vec<weight> dist;
    vec<edge> par;
    void build(int s){
      int n = g.size();
      if(dist.empty()){
        dist.resize(n, inf);
        par.resize(n, edge{});
      }else{
        std::fill(dist.begin(), dist.end(), inf);
        std::fill(par.begin(), par.end(), edge{});
      }
      std::queue<dist_p> que0, que1;
      dist[s] = edge::z();
      que0.push(dist_p(edge::z(), s));
      while(!que0.empty() && !que1.empty()){
        if(que0.empty()){
          que0 = que1;
          que1.clear();
        }
        auto [w, v] = que0.top();
        que0.pop();
        if(dist[v] < w) continue;
        for(edge &e: g[v]){
          weight w = e.wei();
          assert(w == 0 || w == 1);
          weight d = dist[v] + w;
          int to = e.to();
          if(dist[to] > d){
            dist[to] = d;
            par[to] = e;
            if(w == 0) que0.push(dist_p(d, to));
            else que1.push(dist_p(d, to));
          }
        }
      }
    }
    vec<edge> get_path(int v){
      assert(!dist.empty());
      vec<edge> ret;
      while(par[v].from() != -1) ret.push_back(par[v]), v = par[v].from();
      std::reverse(ret.begin(), ret.end());
      return ret;
    }
    weight operator [](int v){return dist[v];}
  };

  // O((V + E)logV)
  // 辺の重みが非負(負の閉路がなければ一応動く)
  template<typename edge>
  struct dijkstra{
  private:
    using weight = typename edge::weight;
    using dist_p = std::pair<weight, int>;
    vec<vec<edge>> &g;
  public:
    dijkstra(vec<vec<edge>> &g): g(g){}
    static constexpr weight inf = std::numeric_limits<weight>::max() / 2;
    static constexpr weight minf = std::numeric_limits<weight>::min() / 2;
    vec<weight> dist;
    vec<edge> par;
    void build(int s){
      int n = g.size();
      if(dist.empty()){
        dist.resize(n, inf);
        par.resize(n, edge{});
      }else{
        std::fill(dist.begin(), dist.end(), inf);
        std::fill(par.begin(), par.end(), edge{});
      }
      std::priority_queue<dist_p, vec<dist_p>, std::greater<dist_p>> que;
      dist[s] = edge::z();
      que.push(dist_p(edge::z(), s));
      while(!que.empty()){
        auto [w, v] = que.top();
        que.pop();
        if(dist[v] < w) continue;
        for(edge &e: g[v]){
          weight d = dist[v] + e.wei();
          int to = e.to();
          if(dist[to] > d){
            dist[to] = d;
            par[to] = e;
            que.push(dist_p(d, to));
          }
        }
      }
    }
    vec<edge> get_path(int v){
      assert(!dist.empty());
      vec<edge> ret;
      while(par[v].from() != -1) ret.push_back(par[v]), v = par[v].from();
      std::reverse(ret.begin(), ret.end());
      return ret;
    }
    weight operator [](int v){return dist[v];}
  };

  // O(VE)
  // inf: 到達不可, minf: 負の閉路
  template<typename edge>
  struct bellman_ford{
  private:
    using weight = typename edge::weight;
    using dist_p = std::pair<weight, int>;
    vec<vec<edge>> &g;
  public:
    bellman_ford(vec<vec<edge>> &g): g(g){}
    static constexpr weight inf = std::numeric_limits<weight>::max() / 2;
    static constexpr weight minf = std::numeric_limits<weight>::min() / 2;
    vec<weight> dist;
    vec<edge> par;

    void build(int s){
      int n = g.size();
      if(dist.empty()){
        dist.resize(n, inf);
        par.resize(n);
      }else{
        std::fill(dist.begin(), dist.end(), inf);
        std::fill(par.begin(), par.end(), edge{});
      }
      dist[s] = edge::z();
      for(int lp = 0; ; lp++){
        bool update = false;
        for(int i = 0; i < n; i++){
          if(dist[i] == inf) continue;
          for(edge e : g[i]){
            weight &dto = dist[e.to()];
            if(dto == minf){
              if(dto != minf) update = true;
              dto = minf;
            }else if(dto == inf || dto > dist[i] + e.wei()){
              dto = (lp > n ? minf : dist[i] + e.wei());
              par[e.to()] = e;
              update = true;
            }
          }
        }
        if(!update) break;
      }
    }
    vec<edge> get_path(int v){
      assert(!dist.empty());
      vec<edge> ret;
      while(par[v].from() != -1) ret.push_back(par[v]), v = par[v].from();
      std::reverse(ret.begin(), ret.end());
      return ret;
    }
    weight operator [](int v){return dist[v];}
  };

  // O(V^3)
  template<typename edge>
  struct warshall_floyd{
  private:
    using weight = typename edge::weight;
    vec<vec<edge>> &g;
  public:
    warshall_floyd(vec<vec<edge>> &g): g(g){}
    static constexpr weight inf = std::numeric_limits<weight>::max() / 2;
    static constexpr weight minf = std::numeric_limits<weight>::min() / 2;
    vec<vec<weight>> dist;
    void build(){
      int n = g.size();
      dist.resize(n, vec<weight>(n, inf));
      for(int i = 0; i < n; i++){
        dist[i][i] = 0;
        for(edge &e : g[i]){
          dist[i][e.to()] = std::min(dist[i][e.to()], e.wei());
        }
      }
      for(int k = 0; k < n; k++){
        for(int s = 0; s < n; s++){
          for(int t = 0; t < n; t++){
            dist[s][t] = std::min(dist[s][t], dist[s][k] + dist[k][t]);
          }
        }
      }
    }
    vec<weight>& operator [](int v){return dist[v];}
  };
};

namespace graph_algorithm{
  // {連結成分, DAG}
  template<typename edge>
  std::pair<vec<int>, vec<vec<int>>> scc(vec<vec<edge>> &g){
    int n = g.size();
    vec<int> v(n), cmp(n, 0);
    vec<vec<int>> rg(n), V;
    auto scc_dfs = [&](auto &&scc_dfs, int cur, int &sz)->void{
      cmp[cur] = -1;
      for(edge &e : g[cur]){
        int to = e.to();
        rg[to].push_back(cur);
        if(cmp[to] == 0) scc_dfs(scc_dfs, to, sz);
      }
      v[sz++] = cur;
    };
    auto scc_rdfs = [&](auto &&scc_rdfs, int cur, const int k)->void{
      cmp[cur] = k;
      V[k].push_back(cur);
      for(int to : rg[cur]) if(cmp[to] == -1) scc_rdfs(scc_rdfs, to, k);
    };
    for(int i = 0, j = 0; i < n; i++) if(!cmp[i]) scc_dfs(scc_dfs, i, j);
    for(int i = (int)v.size() - 1, j = 0; i >= 0; i--){
      if(cmp[v[i]] == -1){
        V.push_back(vec<int>());
        scc_rdfs(scc_rdfs, v[i], j++);
      }
    }
    return {cmp, V};
  }
  // {連結成分, 森}
  template<typename edge>
  std::pair<vec<int>, vec<vec<int>>> two_edge_connected(vec<vec<edge>> &g){
    int n = g.size();
    vec<int> v(n), cmp(n, 0);
    vec<vec<int>> V;
    vec<vec<bool>> edge_used(n);
    auto tec_dfs = [&](auto &&tec_dfs, int cur, int &sz)->void{
      cmp[cur] = -1;
      for(int i = 0; i < g[cur].size(); i++){
        int to = g[cur][i].to();
        if(cmp[to] == 0) edge_used[cur][i] = true, tec_dfs(tec_dfs, to, sz);
      }
      v[sz++] = cur;
    };
    auto tec_rdfs = [&](auto &&tec_rdfs, int cur, const int k)->void{
      cmp[cur] = k;
      V[k].push_back(cur);
      for(int i = 0; i < g[cur].size(); i++){
        int to = g[cur][i].to();
        if(cmp[to] == -1 && !edge_used[cur][i]) tec_rdfs(tec_rdfs, to, k);
      }
    };
    for(int i = 0; i < n; i++) edge_used[i].resize(g[i].size(), 0);
    for(int i = 0, j = 0; i < n; i++) if(!cmp[i]) tec_dfs(tec_dfs, i, j);
    for(int i = (int)v.size() - 1, j = 0; i >= 0; i--){
      if(cmp[v[i]] == -1){
        V.push_back(vec<int>());
        tec_rdfs(tec_rdfs, v[i], j++);
      }
    }
    return {cmp, V};
  }
  // 二重頂点連結成分分解
  // {間接点フラグ, 各連結成分が含む頂点}
  template<typename edge>
  std::pair<vec<bool>, vec<vec<int>>> bcc(vec<vec<edge>> &g){
    int n = g.size();
    vec<vec<int>> V;
    vec<int> child(n, 0), dep(n, -1), low(n);
    vec<bool> used(n, false), is_articulation(n, false);
    vec<edge> tmp_edge;
    auto bcc_dfs = [&](auto &&bcc_dfs, int cur, int par, int d)->void{
      if(par != -1) child[par]++;
      dep[cur] = low[cur] = d;
      for(edge &e : g[cur]){
        int to = e.to();
        if(to == par) continue;
        if(dep[to] < dep[cur]) tmp_edge.push_back(e);
        if(dep[e.to()] == -1){
          bcc_dfs(bcc_dfs, to, cur, d + 1);
          if(low[to] >= dep[cur]){
            is_articulation[cur] = true;
            V.push_back(vec<int>());
            bool is_ok = false;
            while(!tmp_edge.empty() && !is_ok){
              edge e = tmp_edge.back();
              tmp_edge.pop_back();
              if(e.from() == cur && e.to() == to) is_ok = true;
              if(!used[e.to()]) V.back().push_back(e.to()), used[e.to()] = true;
              if(!used[e.from()]) V.back().push_back(e.from()), used[e.from()] = true;
            }
            for(int v : V.back()) used[v] = false;
          }
          low[cur] = std::min(low[cur], low[to]);
        }else low[cur] = std::min(low[cur], dep[to]);
      }
    };
    for(int i = 0; i < n; i++){
      if(dep[i] != -1) continue;
      int vsz_pre = V.size();
      bcc_dfs(bcc_dfs, i, -1, 0);
      is_articulation[i] = (child[i] > 1);
      if(V.size() == vsz_pre) V.push_back(vec<int>{i});// 孤立点
    }
    return {is_articulation, V};
  }
  template<typename edge>
  std::tuple<vec<bool>, vec<int>, vec<vec<simple_edge<int>>>> block_cut_tree(vec<vec<edge>> &g){
    auto [is_articulation, V] = bcc<edge>(g);
    int n = g.size();
    vec<int> cmp(n, -1);
    int m = V.size(), a = m;
    for(int i = 0; i < m; i++){
      for(int v : V[i]){
        if(is_articulation[v]) cmp[v] = a++;
        else cmp[v] = i;
      }
    }
    vec<vec<simple_edge<int>>> G(a);
    for(int i = 0; i < m; i++){
      for(int v : V[i]){
        if(is_articulation[v]){
          G[i].push_back({i, cmp[v]});
          G[cmp[v]].push_back({cmp[v], i});
        }
      }
    }
    return {is_articulation, cmp, G};
  }
};
namespace graph_algorithm{
  // 終了時にinが0でない要素がある -> 閉路が存在する
  // 閉路があるなら空のvectorを返す
  template<typename edge>
  vec<int> topological_sort(vec<vec<edge>> &g){
    int n = g.size();
    std::queue<int> que;
    vec<int> in(n, 0), ret;
    for(int i = 0; i < n; i++) for(edge e : g[i]) in[e.to()]++;
    for(int i = 0; i < n; i++) if(!in[i]) que.push(i);
    while(!que.empty()){
      int p = que.front();
      que.pop();
      ret.push_back(p);
      for(edge &e : g[p]){
        int to = e.to();
        if(!(--in[to])) que.push(to);
      }
    }
    for(int i = 0; i < n; i++) if(in[i] != 0) return {};
    return ret;
  }

  // プリム法, 連結なら始点sは関係ない
  template<typename edge>
  vec<edge> undirected_mst(vec<vec<edge>> &g, int s = 0){
    int n = g.size();
    assert(s < n);
    static vec<bool> V(n, 0);
    vec<edge> ret;
    using pde = std::pair<typename edge::weight, edge>;
    std::priority_queue<pde, vec<pde>, std::function<bool(pde, pde)>> que([](pde a, pde b){
      return a.first > b.first;
    });
    V[s] = true;
    for(edge &e : g[s]) que.push(pde{e.wei(), e});
    while(!que.empty()){
      auto [d, e] = que.top();
      que.pop();
      if(V[e.to()]) continue;
      V[e.to()] = true;
      ret.push_back(e);
      for(edge &ec : g[e.to()]) if(!V[ec.to()]) que.push({ec.wei(), ec});
    }
    for(edge &e : ret) V[e.to()] = V[e.from()] = false;
    return ret;
  }
  // rを根とするbfs木O(V + E)
  template<typename edge>
  vec<vec<edge>> bfs_tree(vec<vec<edge>> &g, int r){
    int n = g.size();
    std::queue<int> que;
    vec<bool> used(n, false);
    que.push(r);
    vec<vec<edge>> ret(n);
    used[r] = true;
    while(!que.empty()){
      int v = que.front();
      que.pop();
      for(edge &e : g[v]){
        int to = e.to();
        if(used[to]) continue;
        used[to] = true;
        ret[v].push_back(e);
        que.push(to);
      }
    }
    return ret;
  }
  // rを根とするbfs木, 最短経路的 O((V + E)logV)
// {木, 重みのテーブル}
  template<typename edge>
  std::pair<vec<vec<edge>>, vec<typename edge::weight>> bfs_tree_shortest(vec<vec<edge>> &g, int r){
    int n = g.size();
    using weight = typename edge::weight;
    using pdv = std::pair<weight, int>;
    static constexpr weight inf = std::numeric_limits<weight>::max() / 2;
    std::priority_queue<pdv, vec<pdv>, std::greater<pdv>> que;
    vec<weight> dist(n, inf);
    dist[r] = edge::z();
    que.push({edge::z(), r});
    vec<vec<edge>> ret(n);
    while(!que.empty()){
      auto [d, v] = que.top();
      que.pop();
      if(dist[v] < d) continue;
      for(edge &e : g[v]){
        int to = e.to();
        weight nxtd = d + e.wei();
        if(dist[to] > nxtd){
          dist[to] = nxtd;
          ret[v].push_back(e);
          que.push({nxtd, to});
        }
      }
    }
    return {ret, dist};
  }
  // g[i]の辺を{同じcmpへの辺, 異なるcmpへの辺}に並び替える, O(V + E)
  template<typename edge>
  void cmp_edge_arrange(const vec<int> &cmp, vec<vec<edge>> &g){
    int n = g.size();
    for(int i = 0; i < n; i++){
      int m = g[i].size();
      int l = 0, r = m - 1;
      while(l < r){
        while(l < m && cmp[i] == cmp[g[i][l].to()]) l++;
        while(0 < r && cmp[i] == cmp[g[i][r].to()]) r--;
        if(l < r) std::swap(g[i][l], g[i][r]);
      }
    }
  }
};

#line 3 "a.cpp"

int main(){
  io_init();
  int n, m;
  std::cin >> n >> m;
  //simple_graph g(n);
  vector<vector<simple_edge<int>>> g(n);

  ll S = 0;
  auto a = read_vec<int>(n);
  range(i, 0, n) S += a[i];
  range(i, 0, m){
    int x, y;
    std::cin >> x >> y;
    x--, y--;
    g[x].push_back({x, y});
    g[y].push_back({y, x});
  }
  vector<vector<simple_edge<int>>> F(0);
  vector<bool> is_articulation;
  vector<int> cmp;
  
  std::tie(is_articulation, cmp, F) = graph_algorithm::block_cut_tree(g);

  int N = F.size();
  vector<ll> cmp_sum(N, 0), cmp_sum_sub(N, -1), cmp_max(N, 0), root(N, -1), parent(N, -1);
  range(i, 0, n) cmp_sum[cmp[i]] += a[i];
  
  auto f = [&](auto &&f, int cur, int par, int r)->void{
    parent[cur] = par;
    root[cur] = r;
    cmp_sum_sub[cur] = cmp_sum[cur];
    for(auto &e : F[cur]){
      if(e.t == par) continue;
      f(f, e.t, cur, r);
      cmp_sum_sub[cur] += cmp_sum_sub[e.t];
    }
  };
  for(int i = 0; i < N; i++){
    if(cmp_sum_sub[i] == -1){
      f(f, i, -1, i);
    }
  }
  for(int i = 0; i < N; i++){
    cmp_max[i] = cmp_sum_sub[root[i]] - cmp_sum_sub[i];
    for(auto &e : F[i]){
      if(e.t == parent[i]) continue;
      cmp_max[i] = max(cmp_max[i], cmp_sum_sub[e.t]);
    }
  }

  vector<ll> ans(n);
  range(i, 0, n){
    if(!is_articulation[i]){
      ans[i] = S - a[i];
    }else{
      ans[i] = cmp_max[cmp[i]];
    }
  }
  //std::cout << cmp_max << '\n';
  range(i, 0, n) std::cout << ans[i] << '\n';
}
accuracy: 1
time_ms: 70
memory_kb: 37956
final_rank: 12

code_snippet: #line 1 "test/graph/bcc/AOJ3022.test.cpp"
#define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=3022"

#line 2 "src/Template.hpp"

#define CUT
#include <bits/stdc++.h>

using namespace std;

#define rep(i, l, r) for (int i = (l); i < (r); ++i)
#define rrep(i, l, r) for (int i = (r); i --> (l);)
#define all(c) begin(c), end(c)

#ifdef LOCAL
#define debug(...) debug_impl(#__VA_ARGS__, __VA_ARGS__)
template <class H, class... Ts> void debug_impl(string s, H&& h, Ts&&... ts) {
  cerr << '(' << s << "): (" << forward<H>(h);
  ((cerr << ", " << forward<Ts>(ts)), ..., (cerr << ")\n"));
}
#else
#define debug(...) void(0)
#endif

template <class T> bool chmax(T& a, const T& b) { return b > a ? (a = b, true) : false; }
template <class T> bool chmin(T& a, const T& b) { return b < a ? (a = b, true) : false; }

template <class T> istream& operator>>(istream& in, vector<T>& v) {
  for (auto& e : v) in >> e;
  return in;
}
template <class ...Args> void read(Args&... args) {
  (cin >> ... >> args);
}
template <class T> ostream& operator<<(ostream& out, const vector<T>& v) {
  int n = v.size();
  rep(i, 0, n) {
    out << v[i];
    if (i + 1 != n) out << ' ';
  }
  return out;
}
template <class H, class ...Ts> void print(H&& h, Ts &&... ts) {
  cout << h, ((cout << ' ' << forward<Ts>(ts)), ..., (cout << '\n'));
}

struct io_setup_ {
  io_setup_() {
    ios::sync_with_stdio(false), cin.tie(nullptr);
    cout << fixed << setprecision(10);
  }
} io_setup{};
#undef CUT

#define NOTE compile command: \texttt{g++ -std=gnu++17 -Wall -Wextra -g -fsanitize=address -fsanitize=undefined \$\{file\} -o \$\{fileDirname\}/\$\{fileBasenameNoExtension\}}
#undef NOTE
#define NOTE \texttt{-DLOCAL} を加えると \texttt{debug(...)} による出力が有効となる
#undef NOTE
#line 3 "src/graph/BCC.hpp"
#define CUT
#line 2 "src/graph/LowLink.hpp"

#line 4 "src/graph/LowLink.hpp"

#define CUT
struct LowLink {
  int n, m;
  vector<pair<int, int>> edges;
  vector<vector<pair<int, int>>> g;
  vector<int> ord, low, a_ids, b_ids;

  bool built = false;

  LowLink(const int n = 0): n(n), m(0), g(n), ord(n, -1), low(n) {}

  // Returns the id of the added edge
  int add_edge(int u, int v) {
    built = false;
    edges.emplace_back(u, v);
    g[u].emplace_back(v, m);
    g[v].emplace_back(u, m);
    return m++;
  }

  void build() {
    if (exchange(built, true)) return;
    int t = 0;
    auto dfs = [&](auto dfs, int u, int id) -> void {
      bool is_root = id < 0, is_art = false;
      int cnt = 0;
      ord[u] = low[u] = t++;
      for (auto [v, id2] : g[u]) if (id != id2) {
        if (ord[v] < 0) {
          ++cnt;
          dfs(dfs, v, id2);
          chmin(low[u], low[v]);
          if (ord[u] <= low[v]) {
            is_art = not is_root;
            if (ord[u] != low[v]) b_ids.push_back(id2);
          }
        } else {
          chmin(low[u], ord[v]);
        }
      }
      if (is_art or (is_root and cnt > 1)) {
        a_ids.push_back(u);
      }
    };
    rep(i, 0, n) if (ord[i] < 0) dfs(dfs, i, -1);
  }

  // Returns `\{i \mid \text{$e_i$ is a bridge} \}`
  const vector<int>& bridge_ids() {
    return build(), b_ids;
  }
  // Returns `\{i \mid \text{$v_i$ is an articulation point} \}`
  const vector<int>& articulation_points() {
    return build(), a_ids;
  }

  bool is_bridge(int u, int v) {
    build();
    if (ord[u] > ord[v]) swap(u, v);
    return ord[u] < low[v];
  }
};
#undef CUT
#line 5 "src/graph/BCC.hpp"

struct BCC {
  // isolated vertex <-> eid is empty
  vector<int> vids, eids;
};

struct BCCDecomp: LowLink {
  // cid[i]: the id of BCC to which `e_i` belongs
  vector<int> cid;
  // isolated vertices
  vector<int> iso;

  BCCDecomp(int n = 0): LowLink(n) {}

  int build() {
    if (built) return iso.size() + (m ? *max_element(all(cid)) + 1 : 0);
    LowLink::build();

    vector<int8_t> used(n);

    int num = 0;
    cid.assign(m, -1);

    auto dfs = [&](auto dfs, int u, int peid) -> void {
      used[u] = true;
      static vector<int> edges;
      for (const auto& [v, eid] : g[u]) if (eid != peid) {
        if (not used[v] or ord[v] < ord[u]) edges.push_back(eid);
        if (used[v]) continue;
        dfs(dfs, v, eid);
        if (low[v] < ord[u]) continue;
        int e;
        do cid[e = edges.back()] = num, edges.pop_back(); while (e != eid);
        num++;
      }
    };

    for (int i = 0; i < n; ++i) if (not used[i]) {
      dfs(dfs, i, -1);
      if (g[i].empty()) iso.push_back(i);
    }
    return num + iso.size();
  }

  vector<BCC> bcc() {
    const int num = build(), vcmp = iso.size(), ecmp = num - vcmp;

    vector<BCC> res(num);
    rep(i, 0, m) {
      res[cid[i]].eids.push_back(i);
    }
    vector<int8_t> seen(n, false);
    rep(id, 0, ecmp) {
      for (int eid : res[id].eids) {
        const auto& [u, v] = edges[eid];
        if (not exchange(seen[u], true)) res[id].vids.push_back(u);
        if (not exchange(seen[v], true)) res[id].vids.push_back(v);
      }
      for (int v : res[id].vids) seen[v] = false;
    }
    rep(id, 0, vcmp) {
      res[ecmp + id].vids = { iso[id] };
    }
    return res;
  }

  // Let `C := \text{set of BCC}` and `A := \text{set of articulation points}`
  // Vertex set of BCT `V := C\sqcup A` (`0 \leq i < |C|` corresponds to the `i`-th BCC and `|C| \leq i < |C| + |A|` corresponds to the `(i-|C|)`-th articulation point)
  // Edge set of BCT `E := \{(c, a) \in C\times A \mid a \in V(C) \}`
  vector<vector<int>> block_cut_tree(const vector<BCC> &bccs) {
    const int cnum = bccs.size(), anum = a_ids.size();

    vector<int> ids(n, -1);
    rep(i, 0, anum) {
      ids[a_ids[i]] = cnum + i;
    }

    vector<vector<int>> res(cnum + anum);
    rep(i, 0, cnum) {
      for (int v : bccs[i].vids) {
        if (int j = ids[v]; j >= 0) {
          res[i].push_back(j);
          res[j].push_back(i);
        }
      }
    }
    return res;
  }

  // Let `C := \text{set of BCC}` and `A := \text{the vertex set of original graph}`
  // Vertex set of BCT `V := C\sqcup A` (`0 \leq i < |C|` corresponds to the `i`-th BCC and `|C| \leq i < |C| + |A|` corresponds to the `(i-|C|)`-th vertex)
  // Edge set of BCT `E := \{(c, a) \in C\times A \mid a \in V(C) \}`
  vector<vector<int>> ext_block_cut_tree(const vector<BCC> &bccs) {
    const int cnum = bccs.size();
    vector<vector<int>> res(cnum + n);
    rep(i, 0, cnum) {
      for (int v : bccs[i].vids) {
        res[i].push_back(cnum + v);
        res[cnum + v].push_back(i);
      }
    }
    return res;
  }
};
#undef CUT

#define NOTE 多重辺・自己ループがあってもよい
#undef NOTE
#line 4 "test/graph/bcc/AOJ3022.test.cpp"

int main() {
  int n, m;
  read(n, m);
  vector<long long> w(n);
  read(w);

  const long long sum = accumulate(all(w), 0LL);

  BCCDecomp bccd(n);
  rep(i, 0, m) {
    int u, v;
    read(u, v);
    --u, --v;
    bccd.add_edge(u, v);
  }
  bccd.build();

  vector<int8_t> is_art(n);
  for (int v : bccd.articulation_points()) {
    is_art[v] = true;
  }

  vector<long long> ans(n);
  rep(i, 0, n) {
    ans[i] = sum - w[i];
  }

  auto bcc = bccd.bcc();
  auto bct = bccd.block_cut_tree(bcc);
  const int k = bcc.size(), l = (int) bct.size() - k;

  vector<long long> s(k + l);
  rep(i, 0, k) {
    for (int v : bcc[i].vids) if (not is_art[v]) {
      s[i] += w[v];
    }
  }
  rep(i, 0, l) {
    s[k + i] = w[bccd.a_ids[i]];
  }

  auto dfs = [&](auto dfs, int u, int p) -> long long {
    long long max_child = 0;
    long long res = s[u];
    for (int v : bct[u]) if (v != p) {
      long long resv = dfs(dfs, v, u);
      chmax(max_child, resv);
      res += resv;
    }
    if (u >= k) {
      chmax(max_child, sum - res);
      ans[bccd.a_ids[u - k]] = max_child;
    }
    return res;
  };
  dfs(dfs, 0, -1);

  rep(i, 0, n) {
    print(ans[i]);
  }
}
accuracy: 1
time_ms: 60
memory_kb: 34288
final_rank: 11

code_snippet: // https://onlinejudge.u-aizu.ac.jp/problems/3022
#pragma GCC optimize("fast-math")

#include <bits/stdc++.h>
#ifdef LOCAL
#  include <dbg.h>
#else
#  define dbg(...) do {} while (0)
#endif

#define cp_lib_4th(_1, _2, _3, x, ...)  x
#define cp_lib_rep(i, l, r)             for (int i = (l); (i) < (r); ++(i))
#define cp_lib_rep0(i, r)               cp_lib_rep(i, 0, r)
#define rep(...)                        cp_lib_4th(__VA_ARGS__, cp_lib_rep, cp_lib_rep0, _)(__VA_ARGS__)
#define cp_lib_repr(i, r, l, ...)       for (int i = (r); (i) >= (l); --(i))
#define repr(...)                       cp_lib_repr(__VA_ARGS__, 0)
#define all(a)                          ::begin(a),::end(a)
#define trav(a, b)                      for (auto&& a : (b))

using namespace std;
using ll = long long;
using ld = long double;
[[maybe_unused]] static constexpr int INF = int(1e9 + 5);
[[maybe_unused]] static constexpr ll INFL = ll(INF) * INF;
template <class C> int sz(const C& c) { return int(::size(c)); }


#ifdef CP_LIB_DEBUG
#define cp_lib_assert(expr) \
    do { if (!(expr)) { \
        ::cerr << "assertion failed: " << #expr << " (" << __FILE__ << ':' << __LINE__ << ")\n"; \
        ::abort(); \
    } } while (0)
#else
#define cp_lib_assert(expr)
#endif


#if __cplusplus < 202002L
struct identity { template <class T> constexpr T&& operator()(T&& t) const noexcept { return forward<T>(t); }; };
#endif
#if __cpp_lib_remove_cvref < 201711L
template <class T> using remove_cvref_t = remove_cv_t<remove_reference_t<T>>;
#endif

namespace cp_lib_type_meta {
    template <class T, class = void> constexpr bool is_tuple_like = false;
    template <class T> constexpr bool is_tuple_like<T, void_t<tuple_element_t<0, T>>> = true;
}


namespace cp_lib_modint { struct ModIntTag {}; }
#include <unistd.h>

namespace cp_lib_io {
    constexpr int BUF_SIZE = 1 << 20;
    constexpr array<array<char, 4>, 10'000> DIGITS = []{
        array<array<char, 4>, 10'000> digits{};
        for (int i = 3, d = 1; i >= 0; --i, d *= 10)
            rep(j, 10'000)
                digits[j][i] = char('0' + j / d % 10);
        return digits;
    }();
    array<char, BUF_SIZE> ibuf, obuf;
    char *iptr = data(ibuf), *iend = iptr, *optr = data(obuf);

    template <class T> constexpr bool is_std_array = false;
    template <class T, size_t I> constexpr bool is_std_array<array<T, I>> = true;

    void flush() {
        for (auto* p = begin(obuf); p != optr; p += write(STDOUT_FILENO, p, optr - p));
        optr = begin(obuf);
    }
    int _flush_atexit = []{ atexit(flush); return 0; }();

    void refill() {
        memmove(begin(ibuf), iptr, iend - iptr);
        iend -= iptr - begin(ibuf);
        iptr = begin(ibuf);
        iend += read(STDIN_FILENO, iend, end(ibuf) - 1 - iend);
        *iend = '\0';
    }

    template <class T, class T2 = remove_cvref_t<T>>
    void print(T&& val) {
        if (end(obuf) - optr < 64)
            flush();

        if constexpr (is_same_v<T2, char>)
            *optr++ = val;
        else if constexpr (is_same_v<T2, bool> || is_same_v<T2, vector<bool>::reference>)
            return print(int(val));
        else if constexpr (is_integral_v<T2> && is_signed_v<T2>) {
            if (val < 0)
                *optr++ = '-';
            using U = make_unsigned_t<T2>;
            return print(U(val < 0 ? -U(val) : U(val)));
        } else if constexpr (is_integral_v<T2> && is_unsigned_v<T2>) {
            T2 val2 = val;
            array<char, 64> tmp;
            char* tptr = end(tmp);
            while (val2 >= 10'000)
                tptr -= 4, memcpy(tptr, &DIGITS[val2 % 10'000][0], 4), val2 /= T2(10'000);
            int d = (val2 >= 100 ? (val2 >= 1000 ? 4 : 3) : (val2 >= 10 ? 2 : 1));
            memcpy(optr, &DIGITS[val2][4 - d], d);
            memcpy(optr + d, tptr, end(tmp) - tptr);
            optr += d + int(end(tmp) - tptr);
        } else if constexpr (is_floating_point_v<T2>)
            optr += sprintf(optr, "%.30Lf", (long double)val);
        else if constexpr (is_convertible_v<T, string_view>) {
            string_view sv(val);
            if (sz(sv) + 1 <= end(obuf) - optr)
                memcpy(optr, data(sv), sz(sv)), optr += sz(sv);
            else {
                flush();
                for (auto *p = data(sv), *pe = p + sz(sv); p != pe; p += write(STDOUT_FILENO, p, pe - p));
            }
        } else if constexpr (is_base_of_v<cp_lib_modint::ModIntTag, T2>)
            return print(decltype(T2::mod())(val));
        else if constexpr (cp_lib_type_meta::is_tuple_like<T2> && !is_std_array<T2>)
            return apply([](auto&&... items) { (print(items), ...); }, forward<T>(val));
        else {
            trav(item, val)
                print(item);
            return;
        }
        *optr++ = ' ';
    }

    template <class T>
    void read(T& val) {
        auto skip_ws = [] {
            do {
                for (; iptr != iend && *iptr <= ' '; ++iptr);
                if (iend - iptr < 64)
                    refill();
            } while (*iptr <= ' ');
        };
        auto read_other = [&](auto other) {
            read(other);
            return other;
        };

        if constexpr (is_same_v<T, char>)
            skip_ws(), val = *iptr++;
        else if constexpr (is_same_v<T, bool> || is_same_v<T, vector<bool>::reference>) {
            val = bool(read_other(uint8_t()));
        } else if constexpr (is_base_of_v<cp_lib_modint::ModIntTag, T>) {
            val = T(read_other(ll()));
        } else if constexpr (is_integral_v<T>) {
            skip_ws();
            if (is_signed_v<T> && *iptr == '-')
                ++iptr, val = T(-read_other(make_unsigned_t<T>()));
            else
                for (val = 0; iptr != iend && *iptr > ' '; val = T(10 * val + (*iptr++ & 15)));
        } else if constexpr (is_floating_point_v<T>)
            skip_ws(), val = T(strtold(iptr, &iptr));
        else if constexpr (is_same_v<T, string>) {
            skip_ws();
            val.clear();
            do {
                auto* after = find_if(iptr, iend, [](char c) { return c <= ' '; });
                val.append(iptr, after);
                if ((iptr = after) != iend)
                    break;
                refill();
            } while (iptr != iend);
        } else if constexpr (cp_lib_type_meta::is_tuple_like<T> && !is_std_array<T>)
            apply([](auto&... items) { (read(items), ...); }, val);
        else
            trav(item, val)
                read(item);
    }
}

using cp_lib_io::flush;

template <class... Args>
void print(Args&&... args) { (cp_lib_io::print(forward<Args>(args)), ...); }

template <class... Args>
void println(Args&&... args) {
    if (sizeof...(Args))
        (cp_lib_io::print(forward<Args>(args)), ...), *(cp_lib_io::optr - 1) = '\n';
    else
        print('\n'), --cp_lib_io::optr;
}

template <class... Args>
void read(Args&... args) { (cp_lib_io::read(args), ...); }



template <class A, class M = identity,
          class = enable_if_t<!cp_lib_type_meta::is_tuple_like<remove_cvref_t<A>>>>
auto graph(A&& adj, M&& m = M()) { return make_tuple(ref(adj), sz(adj), m); }
template <class G, class = enable_if_t<cp_lib_type_meta::is_tuple_like<remove_cvref_t<G>>>>
auto graph(G g) { return g; }
namespace cp_lib_graph {
    template <class G> using AdjListIter = decltype(begin(get<0>(graph(declval<G>()))[0]));
}



namespace cp_lib_graph {
    template <class T, enable_if_t<is_convertible_v<int, remove_cvref_t<T>>, int> = 0>
    auto maybe_edge_idx(T v) { return pair(int(v), 0); }
    template <class T, enable_if_t<!is_convertible_v<int, remove_cvref_t<T>>, int> = 0>
    auto maybe_edge_idx(T p) { auto [v, e] = p; return pair(int(v), int(e)); }
}

template <class G, class OnComp>
void find_biconnected_components(G&& g, OnComp&& on_comp) {
    auto [adj, n, map] = graph(forward<G>(g));
    vector idx(n, INF);
    vector<pair<int, cp_lib_graph::AdjListIter<G>>> stack;

    auto dfs = [&, &adj = adj, &map = map](int v, pair<int, int> pe, auto&& self) -> int {
        int up = idx[v] = sz(stack), cnt = 0;
        for (auto it = begin(adj[v]); it != end(adj[v]); ++it) {
            auto [v2, e] = cp_lib_graph::maybe_edge_idx(map(*it));
            if (pair(v2, e) == pe)
                continue;
            up = min(up, idx[v2]);
            if (idx[v2] == INF || idx[v2] < idx[v])
                stack.emplace_back(v, it);
            if (idx[v2] != INF)
                continue;

            int up2 = self(v2, pair(v, e), self);
            up = min(up, up2);
            if (up2 >= idx[v]) {
                auto cut_v = (pe.first == -1 && !cnt++ ? nullopt : optional(v));
                on_comp(cut_v, begin(stack) + idx[v2] - 1, end(stack));
                stack.resize(idx[v2] - 1);
            }
        }
        return up;
    };

    rep(i, n)
        if (idx[i] == INF)
            dfs(i, pair(-1, 0), dfs);
}

template <class G>
auto block_vertex_tree(G&& g) {
    auto [adj, n, to] = graph(forward<G>(g));
    vector tree(n, vector<int>());
    find_biconnected_components(adj, [&, &to = to](auto, auto it, auto it_end) {
        int vc = sz(tree);
        tree.emplace_back();
        for (; it != it_end; ++it)
            for (int v : {it->first, to(*it->second)})
                if (!sz(tree[v]) || tree[v].back() != vc)
                    tree[v].push_back(vc), tree[vc].push_back(v);
    });
    return tree;
}

int main() {
    int n, m; read(n, m);
    vector w(n, 0ll);
    read(w);
    vector adj(n, vector<int>());
    rep(_, m) {
        int u, v; read(u, v); --u, --v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }

    auto bvt = block_vertex_tree(adj);
    w.resize(sz(bvt));
    auto dfs = [&](int v, int p, auto&& self) -> void {
        trav(v2, bvt[v])
            if (v2 != p)
                self(v2, v, self), w[v] += w[v2];
    };
    dfs(0, -1, dfs);

    rep(i, n) {
        ll ans = w[0] - w[i];
        trav(v, bvt[i])
            if (w[v] < w[i])
                ans = max(ans, w[v]);
        println(ans);
    }
}
accuracy: 1
time_ms: 40
memory_kb: 23884
final_rank: 8

code_snippet: #pragma GCC optimize("fast-math")

#include <bits/stdc++.h>
#ifdef LOCAL
#  include <dbg.h>
#else
#  define dbg(...) do {} while (0)
#endif

#define cp_lib_4th(_1, _2, _3, x, ...)  x
#define cp_lib_rep(i, l, r)             for (int i = (l); (i) < (r); ++(i))
#define cp_lib_rep0(i, r)               cp_lib_rep(i, 0, r)
#define rep(...)                        cp_lib_4th(__VA_ARGS__, cp_lib_rep, cp_lib_rep0, _)(__VA_ARGS__)
#define cp_lib_repr(i, r, l, ...)       for (int i = (r); (i) >= (l); --(i))
#define repr(...)                       cp_lib_repr(__VA_ARGS__, 0)
#define all(a)                          ::begin(a),::end(a)
#define trav(a, b)                      for (auto&& a : (b))

using namespace std;
using ll = long long;
using ld = long double;
[[maybe_unused]] static constexpr int INF = int(1e9 + 5);
[[maybe_unused]] static constexpr ll INFL = ll(INF) * INF;
template <class C> int sz(const C& c) { return int(::size(c)); }


#ifdef CP_LIB_DEBUG
#define cp_lib_assert(expr) \
    do { if (!(expr)) { \
        ::cerr << "assertion failed: " << #expr << " (" << __FILE__ << ':' << __LINE__ << ")\n"; \
        ::abort(); \
    } } while (0)
#else
#define cp_lib_assert(expr)
#endif


#if __cplusplus < 202002L
struct identity { template <class T> constexpr T&& operator()(T&& t) const noexcept { return forward<T>(t); }; };
#endif
#if __cpp_lib_remove_cvref < 201711L
template <class T> using remove_cvref_t = remove_cv_t<remove_reference_t<T>>;
#endif

namespace cp_lib_type_meta {
    struct NoOp { template <class... Args> constexpr void operator()(Args&&...) const noexcept {} };
    template <class T, class = void> constexpr bool is_tuple_like = false;
    template <class T> constexpr bool is_tuple_like<T, void_t<tuple_element_t<0, T>>> = true;
}


namespace cp_lib_modint { struct ModIntTag {}; }
#include <unistd.h>

namespace cp_lib_io {
    constexpr int BUF_SIZE = 1 << 20;
    constexpr array<array<char, 4>, 10'000> DIGITS = []{
        array<array<char, 4>, 10'000> digits{};
        for (int i = 3, d = 1; i >= 0; --i, d *= 10)
            rep(j, 10'000)
                digits[j][i] = char('0' + j / d % 10);
        return digits;
    }();
    array<char, BUF_SIZE> ibuf, obuf;
    char *iptr = data(ibuf), *iend = iptr, *optr = data(obuf);

    template <class T> constexpr bool is_std_array = false;
    template <class T, size_t I> constexpr bool is_std_array<array<T, I>> = true;

    void flush() {
        for (auto* p = begin(obuf); p != optr; p += write(STDOUT_FILENO, p, optr - p));
        optr = begin(obuf);
    }
    int _flush_atexit = []{ atexit(flush); return 0; }();

    void refill() {
        memmove(begin(ibuf), iptr, iend - iptr);
        iend -= iptr - begin(ibuf);
        iptr = begin(ibuf);
        iend += read(STDIN_FILENO, iend, end(ibuf) - 1 - iend);
        *iend = '\0';
    }

    template <class T, class T2 = remove_cvref_t<T>>
    void print(T&& val) {
        if (end(obuf) - optr < 64)
            flush();

        if constexpr (is_same_v<T2, char>)
            *optr++ = val;
        else if constexpr (is_same_v<T2, bool> || is_same_v<T2, vector<bool>::reference>)
            return print(int(val));
        else if constexpr (is_integral_v<T2> && is_signed_v<T2>) {
            if (val < 0)
                *optr++ = '-';
            using U = make_unsigned_t<T2>;
            return print(U(val < 0 ? -U(val) : U(val)));
        } else if constexpr (is_integral_v<T2> && is_unsigned_v<T2>) {
            T2 val2 = val;
            array<char, 64> tmp;
            char* tptr = end(tmp);
            while (val2 >= 10'000)
                tptr -= 4, memcpy(tptr, &DIGITS[val2 % 10'000][0], 4), val2 /= T2(10'000);
            int d = (val2 >= 100 ? (val2 >= 1000 ? 4 : 3) : (val2 >= 10 ? 2 : 1));
            memcpy(optr, &DIGITS[val2][4 - d], d);
            memcpy(optr + d, tptr, end(tmp) - tptr);
            optr += d + int(end(tmp) - tptr);
        } else if constexpr (is_floating_point_v<T2>)
            optr += sprintf(optr, "%.30Lf", (long double)val);
        else if constexpr (is_convertible_v<T, string_view>) {
            string_view sv(val);
            if (sz(sv) + 1 <= end(obuf) - optr)
                memcpy(optr, data(sv), sz(sv)), optr += sz(sv);
            else {
                flush();
                for (auto *p = data(sv), *pe = p + sz(sv); p != pe; p += write(STDOUT_FILENO, p, pe - p));
            }
        } else if constexpr (is_base_of_v<cp_lib_modint::ModIntTag, T2>)
            return print(decltype(T2::mod())(val));
        else if constexpr (cp_lib_type_meta::is_tuple_like<T2> && !is_std_array<T2>)
            return apply([](auto&&... items) { (print(items), ...); }, forward<T>(val));
        else {
            trav(item, val)
                print(item);
            return;
        }
        *optr++ = ' ';
    }

    template <class T>
    void read(T& val) {
        auto skip_ws = [] {
            do {
                for (; iptr != iend && *iptr <= ' '; ++iptr);
                if (iend - iptr < 64)
                    refill();
            } while (*iptr <= ' ');
        };
        auto read_other = [&](auto other) {
            read(other);
            return other;
        };

        if constexpr (is_same_v<T, char>)
            skip_ws(), val = *iptr++;
        else if constexpr (is_same_v<T, bool> || is_same_v<T, vector<bool>::reference>) {
            val = bool(read_other(uint8_t()));
        } else if constexpr (is_base_of_v<cp_lib_modint::ModIntTag, T>) {
            val = T(read_other(ll()));
        } else if constexpr (is_integral_v<T>) {
            skip_ws();
            if (is_signed_v<T> && *iptr == '-')
                ++iptr, val = T(-read_other(make_unsigned_t<T>()));
            else
                for (val = 0; iptr != iend && *iptr > ' '; val = T(10 * val + (*iptr++ & 15)));
        } else if constexpr (is_floating_point_v<T>)
            skip_ws(), val = T(strtold(iptr, &iptr));
        else if constexpr (is_same_v<T, string>) {
            skip_ws();
            val.clear();
            do {
                auto* after = find_if(iptr, iend, [](char c) { return c <= ' '; });
                val.append(iptr, after);
                if ((iptr = after) != iend)
                    break;
                refill();
            } while (iptr != iend);
        } else if constexpr (cp_lib_type_meta::is_tuple_like<T> && !is_std_array<T>)
            apply([](auto&... items) { (read(items), ...); }, val);
        else
            trav(item, val)
                read(item);
    }
}

using cp_lib_io::flush;

template <class... Args>
void print(Args&&... args) { (cp_lib_io::print(forward<Args>(args)), ...); }

template <class... Args>
void println(Args&&... args) {
    if (sizeof...(Args))
        (cp_lib_io::print(forward<Args>(args)), ...), *(cp_lib_io::optr - 1) = '\n';
    else
        print('\n'), --cp_lib_io::optr;
}

template <class... Args>
void read(Args&... args) { (cp_lib_io::read(args), ...); }
// #include "cp-lib/graph/lca.hpp"

template <class A, class M>
struct NewGraph {
    A& adj;
    int n;
    M map;

    using Mapped = decltype(declval<M>()(*begin(declval<A>()[0])));

    NewGraph(A& adj_, M map_) : adj(adj_), n(sz(adj)), map(move(map_)) {}
    explicit NewGraph(A& adj_) : NewGraph(adj_, identity()) {}
};

template <class A> NewGraph(A&) -> NewGraph<A, identity>;

template <class G, class OnComp>
void biconnected_components(G&& graph, OnComp&& on_comp) {
    auto [adj, n, map] = NewGraph(forward<G>(graph));
    auto normalize = [&](auto mapped) {
        if constexpr(is_convertible_v<int, decltype(mapped)>)
            return pair(int(mapped), 0);
        else
            return mapped;
    };
    vector idx(n, INF);
    vector<pair<int, decltype(begin(adj[0]))>> stack;

    auto dfs = [&, &adj = adj, &map = map](int v, pair<int, int> pe, auto&& self) -> int {
        int up = idx[v] = sz(stack), cnt = 0;
        for (auto it = begin(adj[v]); it != end(adj[v]); ++it) {
            auto [v2, e] = normalize(map(*it));
            if (pair(v2, e) == pe)
                continue;
            up = min(up, idx[v2]);
            if (idx[v2] == INF || idx[v2] < idx[v])
                stack.emplace_back(v, it);
            if (idx[v2] != INF)
                continue;

            int up2 = self(v2, pair(v, e), self);
            up = min(up, up2);
            if (up2 >= idx[v]) {
                auto cut_v = (pe.first == -1 && !cnt++ ? nullopt : optional(v));
                on_comp(cut_v, begin(stack) + idx[v2] - 1, end(stack));
                stack.resize(idx[v2] - 1);
            }
        }
        return up;
    };

    rep(i, n)
        if (idx[i] == INF)
            dfs(i, pair(-1, 0), dfs);
}

template <class G>
vector<vector<int>> block_vertex_tree(G&& graph) {
    NewGraph g(forward<G>(graph));
    vector adj(g.n, vector<int>());
    biconnected_components(g, [&](auto, auto it, auto it_end) {
        int vc = sz(adj);
        adj.emplace_back();
        for (; it != it_end; ++it)
            for (int v : {it->first, g.map(*it->second)})
                if (!sz(adj[v]) || adj[v].back() != vc)
                    adj[v].push_back(vc), adj[vc].push_back(v);
    });
    return adj;
}

int main() {
    // int n, m; read(n, m);
    // vector adj(n, vector<pair<int, int>>());
    // rep(i, m) {
    //     int u, v; read(u, v);
    //     adj[u].emplace_back(v, i);
    //     adj[v].emplace_back(u, i);
    // }

    // vector<vector<int>> bicomps;
    // biconnected_components(adj, [&](auto, auto it, auto it_end) {
    //     auto& comp = bicomps.emplace_back();
    //     for (; it != it_end; ++it)
    //         comp.push_back(it->second->second);
    // });

    // println(sz(bicomps));
    // trav(comp, bicomps)
    //     println(sz(comp), comp);


    // int n, m; read(n, m);
    // vector adj(n, vector<int>());
    // rep(_, m) {
    //     int u, v; read(u, v);
    //     adj[u].push_back(v);
    //     adj[v].push_back(u);
    // }

    // set<int> cut_vertices;
    // biconnected_components(adj, [&](auto cut_v, auto, auto) {
    //     if (cut_v)
    //         cut_vertices.emplace(*cut_v);
    // });

    // trav(v, cut_vertices)
    //     println(v);


    int n, m; read(n, m);
    vector w(n, 0);
    read(w);
    vector adj(n, vector<int>());
    rep(_, m) {
        int u, v; read(u, v); --u, --v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }

    auto bvt = block_vertex_tree(adj);
    int nt = sz(bvt);
    vector wsum(nt, 0ll);
    copy(all(w), begin(wsum));
    auto dfs = [&](int v, int p, auto&& self) -> void {
        trav(v2, bvt[v])
            if (v2 != p)
                self(v2, v, self), wsum[v] += wsum[v2];
    };
    dfs(0, -1, dfs);

    rep(i, n) {
        if (sz(bvt[i]) == 1) {
            println(wsum[0] - w[i]);
            continue;
        }

        ll mx = wsum[0] - wsum[i];
        trav(v, bvt[i])
            if (wsum[v] < wsum[i])
                mx = max(mx, wsum[v]);
        println(mx);
    }


    // int n, m; read(n, m);
    // vector adj(n, vector<int>());
    // rep(_, m) {
    //     int u, v; read(u, v); --u, --v;
    //     adj[u].push_back(v);
    //     adj[v].push_back(u);
    // }
}
accuracy: 1
time_ms: 30
memory_kb: 24228
final_rank: 6

code_snippet: #pragma GCC optimize("fast-math")

#include <bits/stdc++.h>
#ifdef LOCAL
#  include <dbg.h>
#else
#  define dbg(...) do {} while (0)
#endif

#define cp_lib_4th(_1, _2, _3, x, ...)  x
#define cp_lib_rep(i, l, r)             for (int i = (l); (i) < (r); ++(i))
#define cp_lib_rep0(i, r)               cp_lib_rep(i, 0, r)
#define rep(...)                        cp_lib_4th(__VA_ARGS__, cp_lib_rep, cp_lib_rep0, _)(__VA_ARGS__)
#define cp_lib_repr(i, r, l, ...)       for (int i = (r); (i) >= (l); --(i))
#define repr(...)                       cp_lib_repr(__VA_ARGS__, 0)
#define all(a)                          ::begin(a),::end(a)
#define trav(a, b)                      for (auto&& a : (b))

using namespace std;
using ll = long long;
using ld = long double;
[[maybe_unused]] static constexpr int INF = int(1e9 + 5);
[[maybe_unused]] static constexpr ll INFL = ll(INF) * INF;
template <class C> int sz(const C& c) { return int(::size(c)); }


#ifdef CP_LIB_DEBUG
#define cp_lib_assert(expr) \
    do { if (!(expr)) { \
        ::cerr << "assertion failed: " << #expr << " (" << __FILE__ << ':' << __LINE__ << ")\n"; \
        ::abort(); \
    } } while (0)
#else
#define cp_lib_assert(expr)
#endif


#if __cplusplus < 202002L
struct identity { template <class T> constexpr T&& operator()(T&& t) const noexcept { return forward<T>(t); }; };
#endif
#if __cpp_lib_remove_cvref < 201711L
template <class T> using remove_cvref_t = remove_cv_t<remove_reference_t<T>>;
#endif

namespace cp_lib_type_meta {
    struct NoOp { template <class... Args> constexpr void operator()(Args&&...) const noexcept {} };
    template <class T, class = void> constexpr bool is_tuple_like = false;
    template <class T> constexpr bool is_tuple_like<T, void_t<tuple_element_t<0, T>>> = true;
}


namespace cp_lib_modint { struct ModIntTag {}; }
#include <unistd.h>

namespace cp_lib_io {
    constexpr int BUF_SIZE = 1 << 20;
    constexpr array<array<char, 4>, 10'000> DIGITS = []{
        array<array<char, 4>, 10'000> digits{};
        for (int i = 3, d = 1; i >= 0; --i, d *= 10)
            rep(j, 10'000)
                digits[j][i] = char('0' + j / d % 10);
        return digits;
    }();
    array<char, BUF_SIZE> ibuf, obuf;
    char *iptr = data(ibuf), *iend = iptr, *optr = data(obuf);

    template <class T> constexpr bool is_std_array = false;
    template <class T, size_t I> constexpr bool is_std_array<array<T, I>> = true;

    void flush() {
        for (auto* p = begin(obuf); p != optr; p += write(STDOUT_FILENO, p, optr - p));
        optr = begin(obuf);
    }
    int _flush_atexit = []{ atexit(flush); return 0; }();

    void refill() {
        memmove(begin(ibuf), iptr, iend - iptr);
        iend -= iptr - begin(ibuf);
        iptr = begin(ibuf);
        iend += read(STDIN_FILENO, iend, end(ibuf) - 1 - iend);
        *iend = '\0';
    }

    template <class T, class T2 = remove_cvref_t<T>>
    void print(T&& val) {
        if (end(obuf) - optr < 64)
            flush();

        if constexpr (is_same_v<T2, char>)
            *optr++ = val;
        else if constexpr (is_same_v<T2, bool> || is_same_v<T2, vector<bool>::reference>)
            return print(int(val));
        else if constexpr (is_integral_v<T2> && is_signed_v<T2>) {
            if (val < 0)
                *optr++ = '-';
            using U = make_unsigned_t<T2>;
            return print(U(val < 0 ? -U(val) : U(val)));
        } else if constexpr (is_integral_v<T2> && is_unsigned_v<T2>) {
            T2 val2 = val;
            array<char, 64> tmp;
            char* tptr = end(tmp);
            while (val2 >= 10'000)
                tptr -= 4, memcpy(tptr, &DIGITS[val2 % 10'000][0], 4), val2 /= T2(10'000);
            int d = (val2 >= 100 ? (val2 >= 1000 ? 4 : 3) : (val2 >= 10 ? 2 : 1));
            memcpy(optr, &DIGITS[val2][4 - d], d);
            memcpy(optr + d, tptr, end(tmp) - tptr);
            optr += d + int(end(tmp) - tptr);
        } else if constexpr (is_floating_point_v<T2>)
            optr += sprintf(optr, "%.30Lf", (long double)val);
        else if constexpr (is_convertible_v<T, string_view>) {
            string_view sv(val);
            if (sz(sv) + 1 <= end(obuf) - optr)
                memcpy(optr, data(sv), sz(sv)), optr += sz(sv);
            else {
                flush();
                for (auto *p = data(sv), *pe = p + sz(sv); p != pe; p += write(STDOUT_FILENO, p, pe - p));
            }
        } else if constexpr (is_base_of_v<cp_lib_modint::ModIntTag, T2>)
            return print(decltype(T2::mod())(val));
        else if constexpr (cp_lib_type_meta::is_tuple_like<T2> && !is_std_array<T2>)
            return apply([](auto&&... items) { (print(items), ...); }, forward<T>(val));
        else {
            trav(item, val)
                print(item);
            return;
        }
        *optr++ = ' ';
    }

    template <class T>
    void read(T& val) {
        auto skip_ws = [] {
            do {
                for (; iptr != iend && *iptr <= ' '; ++iptr);
                if (iend - iptr < 64)
                    refill();
            } while (*iptr <= ' ');
        };
        auto read_other = [&](auto other) {
            read(other);
            return other;
        };

        if constexpr (is_same_v<T, char>)
            skip_ws(), val = *iptr++;
        else if constexpr (is_same_v<T, bool> || is_same_v<T, vector<bool>::reference>) {
            val = bool(read_other(uint8_t()));
        } else if constexpr (is_base_of_v<cp_lib_modint::ModIntTag, T>) {
            val = T(read_other(ll()));
        } else if constexpr (is_integral_v<T>) {
            skip_ws();
            if (is_signed_v<T> && *iptr == '-')
                ++iptr, val = T(-read_other(make_unsigned_t<T>()));
            else
                for (val = 0; iptr != iend && *iptr > ' '; val = T(10 * val + (*iptr++ & 15)));
        } else if constexpr (is_floating_point_v<T>)
            skip_ws(), val = T(strtold(iptr, &iptr));
        else if constexpr (is_same_v<T, string>) {
            skip_ws();
            val.clear();
            do {
                auto* after = find_if(iptr, iend, [](char c) { return c <= ' '; });
                val.append(iptr, after);
                if ((iptr = after) != iend)
                    break;
                refill();
            } while (iptr != iend);
        } else if constexpr (cp_lib_type_meta::is_tuple_like<T> && !is_std_array<T>)
            apply([](auto&... items) { (read(items), ...); }, val);
        else
            trav(item, val)
                read(item);
    }
}

using cp_lib_io::flush;

template <class... Args>
void print(Args&&... args) { (cp_lib_io::print(forward<Args>(args)), ...); }

template <class... Args>
void println(Args&&... args) {
    if (sizeof...(Args))
        (cp_lib_io::print(forward<Args>(args)), ...), *(cp_lib_io::optr - 1) = '\n';
    else
        print('\n'), --cp_lib_io::optr;
}

template <class... Args>
void read(Args&... args) { (cp_lib_io::read(args), ...); }


template <class A, class M>
struct Graph {
    const A& adj;
    int n;
    M map;

    Graph(const A& adj_, int n_, M map_) : adj(adj_), n(n_), map(move(map_)) {}
    Graph(const A& adj_, M map_) : Graph(adj_, sz(adj_), move(map_)) {}
    Graph(const A& adj_, int n_) : Graph(adj_, n_, identity()) {}
    explicit Graph(const A& adj_) : Graph(adj_, identity()) {}
};

template <class A> Graph(const A&, int) -> Graph<A, identity>;
template <class A> Graph(const A&) -> Graph<A, identity>;



template <class T> constexpr inline bool is_pow2(T n) { return n && !(n & (n - 1)); }
template <class T> constexpr inline int floor_log2(T n) { return n ? 63 - __builtin_clzll(n) : 0; }
template <class T> constexpr inline int ceil_log2(T n) { return n ? floor_log2(n) + !is_pow2(n) : 0; }

namespace cp_lib_rmq {
    template <class T, bool Max> T minmax(T a, T b) { return (a < b) ^ Max ? a : b; }
}

template <class T, T (*Combine)(T, T)>
struct SparseTable {
    vector<vector<T>> d = {};

    SparseTable() = default;
    explicit SparseTable(const vector<T>& v) {
        int n = sz(v), k = floor_log2(n);
        d.assign(k + 1, v);
        rep(i, k) rep(j, n)
            d[i + 1][j] = Combine(d[i][j], d[i][min(j + (1 << i), n - 1)]);
    }

    // Aggregate for [l, r)
    T query(int l, int r) const {
        int k = floor_log2(r - l);
        return Combine(d[k][l], d[k][r - (1 << k)]);
    }
};

template <class T>
using Rmq = SparseTable<T, cp_lib_rmq::minmax<T, false>>;
template <class T>
using Rmaxq = SparseTable<T, cp_lib_rmq::minmax<T, true>>;

struct LowestCommonAncestor {
    vector<int> time, euler;
    Rmq<int> rmq;

    template <class G, class = enable_if_t<!is_same_v<LowestCommonAncestor, remove_cvref_t<G>>>>
    LowestCommonAncestor(G&& graph, int root = 0) {
        auto [adj, n, to] = Graph(forward<G>(graph));
        if (!n) return;
        time = vector(n, -1);
        vector<int> d;
        auto dfs = [&, t=1, &adj=adj, &to=to](int v, int p, int tp, auto&& self) mutable -> void {
            euler.push_back(p);
            d.push_back(tp);
            time[v] = t++;
            trav(e, adj[v])
                if (to(e) != p)
                    self(to(e), v, time[v], self);
        };
        dfs(root, -1, 0, dfs);
        rep(i, n)
            if (time[i] == -1)
                dfs(i, -1, 0, dfs);
        rmq = Rmq<int>(d);
    }

    int lca(int u, int v) const {
        if (u == v) return u;
        auto [l, r] = minmax(time[u], time[v]);
        return euler[rmq.query(l, r)];
    }

    bool on_path(int v, pair<int, int> path) const {
        auto [a, b] = path;
        auto av = lca(a, v), bv = lca(b, v), ab = lca(a, b);
        return av != -1 && bv != -1 && ab != -1 && minmax(av, bv) == minmax(v, ab);
    }

    bool is_ancestor(int u, int v) const { return lca(u, v) == u; }
};

template <class G, class OnCut, class OnComp>
void biconnected_components(G&& graph, OnCut&& on_cut, OnComp&& on_comp) {
    auto [adj, n, map] = Graph(forward<G>(graph));
    vector idx(n, INF);
    vector<pair<int, decltype(begin(adj[0]))>> stack;

    auto make_component = [&](int rem) {
        on_comp(begin(stack) + rem, end(stack));
        stack.resize(rem);
    };
    auto dfs = [&, &adj=adj, &map=map](int v, auto pe, int root, auto&& self) -> int {
        int up = idx[v] = sz(stack);
        for (auto it = begin(adj[v]); it != end(adj[v]); ++it) {
            auto [v2, e] = map(*it);
            if (optional(e) == pe)
                continue;
            up = min(up, idx[v2]);
            if (idx[v2] == INF || idx[v2] < idx[v])
                stack.emplace_back(v, it);
            if (idx[v2] != INF)
                continue;

            int up2 = self(v2, optional(e), 0, self);
            up = min(up, up2);
            if (up2 >= idx[v]) {
                make_component(idx[v2] - 1);
                if (--root < 1)
                    on_cut(v);
            }
        }
        return up;
    };

    rep(i, n)
        if (idx[i] == INF)
            dfs(i, nullopt, 2, dfs);
}

struct BlockVertexTree {
    vector<vector<int>> adj;

    template <class G, class = enable_if_t<!is_same_v<BlockVertexTree, remove_cvref_t<G>>>>
    explicit BlockVertexTree(G&& graph) {
        Graph g(forward<G>(graph));
        auto [_, n, map] = g;
        adj.resize(n);

        biconnected_components(
            g, [](auto) {},
            [&, &map=map](auto it, auto it_end) {
                int vc = sz(adj);
                adj.emplace_back();
                for (; it != it_end; ++it) {
                    auto [v2, _2] = map(*it->second);
                    for (int v : {it->first, v2})
                        if (!sz(adj[v]) || adj[v].back() != vc)
                            adj[v].push_back(vc), adj[vc].push_back(v);
                }
            });
    }

    bool is_cut(int v) { return sz(adj[v]) == 1; }
};

int main() {
    // int n, m; read(n, m);
    // vector adj(n, vector<pair<int, int>>());
    // rep(i, m) {
    //     int u, v; read(u, v);
    //     adj[u].emplace_back(v, i);
    //     adj[v].emplace_back(u, i);
    // }

    // vector<vector<int>> bicomps;
    // biconnected_components(adj, [](auto&&...) {}, [&](auto it, auto it_end) {
    //     auto& comp = bicomps.emplace_back();
    //     for (; it != it_end; ++it)
    //         comp.push_back(it->second->second);
    // });

    // println(sz(bicomps));
    // trav(comp, bicomps)
    //     println(sz(comp), comp);

    // int n, m; read(n, m);
    // vector adj(n, vector<pair<int, int>>());
    // rep(i, m) {
    //     int u, v; read(u, v);
    //     adj[u].emplace_back(v, i);
    //     adj[v].emplace_back(u, i);
    // }

    // vector is_cut(n, false);
    // biconnected_components(adj, [&](int v) { is_cut[v] = true; }, [](auto&&...) {});

    // rep(i, n)
    //     if (is_cut[i])
    //         println(i);

    int n, m; read(n, m);
    vector w(n, 0);
    read(w);
    vector adj(n, vector<pair<int, int>>());
    rep(i, m) {
        int u, v; read(u, v); --u, --v;
        adj[u].emplace_back(v, i);
        adj[v].emplace_back(u, i);
    }

    BlockVertexTree bvt(adj);
    int nt = sz(bvt.adj);
    vector wsum(nt, 0ll);
    copy(all(w), begin(wsum));
    auto dfs = [&](int v, int p, auto&& self) -> void {
        trav(v2, bvt.adj[v])
            if (v2 != p)
                self(v2, v, self), wsum[v] += wsum[v2];
    };
    dfs(0, -1, dfs);

    rep(i, n) {
        if (bvt.is_cut(i)) {
            println(wsum[0] - w[i]);
            continue;
        }

        ll mx = wsum[0] - wsum[i];
        trav(v, bvt.adj[i])
            if (wsum[v] < wsum[i])
                mx = max(mx, wsum[v]);
        println(mx);
    }

    // int n, m; read(n, m);
    // vector adj(n, vector<int>());
    // rep(_, m) {
    //     int u, v; read(u, v); --u, --v;
    //     adj[u].push_back(v);
    //     adj[v].push_back(u);
    // }
}
accuracy: 1
time_ms: 40
memory_kb: 24716
final_rank: 9

code_snippet: #pragma GCC optimize("fast-math")

#include <bits/stdc++.h>
#ifdef LOCAL
#  include <dbg.h>
#else
#  define dbg(...) do {} while (0)
#endif

#define cp_lib_4th(_1, _2, _3, x, ...)  x
#define cp_lib_rep(i, l, r)             for (int i = (l); (i) < (r); ++(i))
#define cp_lib_rep0(i, r)               cp_lib_rep(i, 0, r)
#define rep(...)                        cp_lib_4th(__VA_ARGS__, cp_lib_rep, cp_lib_rep0, _)(__VA_ARGS__)
#define cp_lib_repr(i, r, l, ...)       for (int i = (r); (i) >= (l); --(i))
#define repr(...)                       cp_lib_repr(__VA_ARGS__, 0)
#define all(a)                          ::begin(a),::end(a)
#define trav(a, b)                      for (auto&& a : (b))

using namespace std;
using ll = long long;
using ld = long double;
[[maybe_unused]] static constexpr int INF = int(1e9 + 5);
[[maybe_unused]] static constexpr ll INFL = ll(INF) * INF;
template <class C> int sz(const C& c) { return int(::size(c)); }


#ifdef CP_LIB_DEBUG
#define cp_lib_assert(expr) \
    do { if (!(expr)) { \
        ::cerr << "assertion failed: " << #expr << " (" << __FILE__ << ':' << __LINE__ << ")\n"; \
        ::abort(); \
    } } while (0)
#else
#define cp_lib_assert(expr)
#endif


#if __cplusplus < 202002L
struct identity { template <class T> constexpr T&& operator()(T&& t) const noexcept { return forward<T>(t); }; };
#endif
#if __cpp_lib_remove_cvref < 201711L
template <class T> using remove_cvref_t = remove_cv_t<remove_reference_t<T>>;
#endif

namespace cp_lib_type_meta {
    struct NoOp { template <class... Args> constexpr void operator()(Args&&...) const noexcept {} };
    template <class T, class = void> constexpr bool is_tuple_like = false;
    template <class T> constexpr bool is_tuple_like<T, void_t<tuple_element_t<0, T>>> = true;
}


namespace cp_lib_modint { struct ModIntTag {}; }
#include <unistd.h>

namespace cp_lib_io {
    constexpr int BUF_SIZE = 1 << 20;
    constexpr array<array<char, 4>, 10'000> DIGITS = []{
        array<array<char, 4>, 10'000> digits{};
        for (int i = 3, d = 1; i >= 0; --i, d *= 10)
            rep(j, 10'000)
                digits[j][i] = char('0' + j / d % 10);
        return digits;
    }();
    array<char, BUF_SIZE> ibuf, obuf;
    char *iptr = data(ibuf), *iend = iptr, *optr = data(obuf);

    template <class T> constexpr bool is_std_array = false;
    template <class T, size_t I> constexpr bool is_std_array<array<T, I>> = true;

    void flush() {
        for (auto* p = begin(obuf); p != optr; p += write(STDOUT_FILENO, p, optr - p));
        optr = begin(obuf);
    }
    int _flush_atexit = []{ atexit(flush); return 0; }();

    void refill() {
        memmove(begin(ibuf), iptr, iend - iptr);
        iend -= iptr - begin(ibuf);
        iptr = begin(ibuf);
        iend += read(STDIN_FILENO, iend, end(ibuf) - 1 - iend);
        *iend = '\0';
    }

    template <class T, class T2 = remove_cvref_t<T>>
    void print(T&& val) {
        if (end(obuf) - optr < 64)
            flush();

        if constexpr (is_same_v<T2, char>)
            *optr++ = val;
        else if constexpr (is_same_v<T2, bool> || is_same_v<T2, vector<bool>::reference>)
            return print(int(val));
        else if constexpr (is_integral_v<T2> && is_signed_v<T2>) {
            if (val < 0)
                *optr++ = '-';
            using U = make_unsigned_t<T2>;
            return print(U(val < 0 ? -U(val) : U(val)));
        } else if constexpr (is_integral_v<T2> && is_unsigned_v<T2>) {
            T2 val2 = val;
            array<char, 64> tmp;
            char* tptr = end(tmp);
            while (val2 >= 10'000)
                tptr -= 4, memcpy(tptr, &DIGITS[val2 % 10'000][0], 4), val2 /= T2(10'000);
            int d = (val2 >= 100 ? (val2 >= 1000 ? 4 : 3) : (val2 >= 10 ? 2 : 1));
            memcpy(optr, &DIGITS[val2][4 - d], d);
            memcpy(optr + d, tptr, end(tmp) - tptr);
            optr += d + int(end(tmp) - tptr);
        } else if constexpr (is_floating_point_v<T2>)
            optr += sprintf(optr, "%.30Lf", (long double)val);
        else if constexpr (is_convertible_v<T, string_view>) {
            string_view sv(val);
            if (sz(sv) + 1 <= end(obuf) - optr)
                memcpy(optr, data(sv), sz(sv)), optr += sz(sv);
            else {
                flush();
                for (auto *p = data(sv), *pe = p + sz(sv); p != pe; p += write(STDOUT_FILENO, p, pe - p));
            }
        } else if constexpr (is_base_of_v<cp_lib_modint::ModIntTag, T2>)
            return print(decltype(T2::mod())(val));
        else if constexpr (cp_lib_type_meta::is_tuple_like<T2> && !is_std_array<T2>)
            return apply([](auto&&... items) { (print(items), ...); }, forward<T>(val));
        else {
            trav(item, val)
                print(item);
            return;
        }
        *optr++ = ' ';
    }

    template <class T>
    void read(T& val) {
        auto skip_ws = [] {
            do {
                for (; iptr != iend && *iptr <= ' '; ++iptr);
                if (iend - iptr < 64)
                    refill();
            } while (*iptr <= ' ');
        };
        auto read_other = [&](auto other) {
            read(other);
            return other;
        };

        if constexpr (is_same_v<T, char>)
            skip_ws(), val = *iptr++;
        else if constexpr (is_same_v<T, bool> || is_same_v<T, vector<bool>::reference>) {
            val = bool(read_other(uint8_t()));
        } else if constexpr (is_base_of_v<cp_lib_modint::ModIntTag, T>) {
            val = T(read_other(ll()));
        } else if constexpr (is_integral_v<T>) {
            skip_ws();
            if (is_signed_v<T> && *iptr == '-')
                ++iptr, val = T(-read_other(make_unsigned_t<T>()));
            else
                for (val = 0; iptr != iend && *iptr > ' '; val = T(10 * val + (*iptr++ & 15)));
        } else if constexpr (is_floating_point_v<T>)
            skip_ws(), val = T(strtold(iptr, &iptr));
        else if constexpr (is_same_v<T, string>) {
            skip_ws();
            val.clear();
            do {
                auto* after = find_if(iptr, iend, [](char c) { return c <= ' '; });
                val.append(iptr, after);
                if ((iptr = after) != iend)
                    break;
                refill();
            } while (iptr != iend);
        } else if constexpr (cp_lib_type_meta::is_tuple_like<T> && !is_std_array<T>)
            apply([](auto&... items) { (read(items), ...); }, val);
        else
            trav(item, val)
                read(item);
    }
}

using cp_lib_io::flush;

template <class... Args>
void print(Args&&... args) { (cp_lib_io::print(forward<Args>(args)), ...); }

template <class... Args>
void println(Args&&... args) {
    if (sizeof...(Args))
        (cp_lib_io::print(forward<Args>(args)), ...), *(cp_lib_io::optr - 1) = '\n';
    else
        print('\n'), --cp_lib_io::optr;
}

template <class... Args>
void read(Args&... args) { (cp_lib_io::read(args), ...); }


template <class A, class M>
struct Graph {
    const A& adj;
    int n;
    M map;

    Graph(const A& adj_, int n_, M map_) : adj(adj_), n(n_), map(move(map_)) {}
    Graph(const A& adj_, M map_) : Graph(adj_, sz(adj_), move(map_)) {}
    Graph(const A& adj_, int n_) : Graph(adj_, n_, identity()) {}
    explicit Graph(const A& adj_) : Graph(adj_, identity()) {}
};

template <class A> Graph(const A&, int) -> Graph<A, identity>;
template <class A> Graph(const A&) -> Graph<A, identity>;

template <class G, class OnCut, class OnComp>
void biconnected_components(G&& graph, OnCut&& on_cut, OnComp&& on_comp) {
    auto [adj, n, map] = Graph(forward<G>(graph));
    vector idx(n, INF);
    vector<pair<int, decltype(begin(adj[0]))>> stack;

    auto make_component = [&](int rem) {
        on_comp(begin(stack) + rem, end(stack));
        stack.resize(rem);
    };
    auto dfs = [&, &adj=adj, &map=map](int v, auto pe, int root, auto&& self) -> int {
        int up = idx[v] = sz(stack);
        for (auto it = begin(adj[v]); it != end(adj[v]); ++it) {
            auto [v2, e] = map(*it);
            if (optional(e) == pe)
                continue;
            up = min(up, idx[v2]);
            if (idx[v2] == INF || idx[v2] < idx[v])
                stack.emplace_back(v, it);
            if (idx[v2] != INF)
                continue;

            int up2 = self(v2, optional(e), 0, self);
            up = min(up, up2);
            if (up2 >= idx[v]) {
                if (root == 2)
                    --root;
                else if (root == 1)
                    --root, on_cut(v), make_component(idx[v2] - 1), make_component(0);
                else
                    on_cut(v), make_component(idx[v2] - 1);
            }
        }
        return up;
    };

    rep(i, n) {
        if (idx[i] != INF)
            continue;
        dfs(i, nullopt, 2, dfs);
        if (sz(stack))
            make_component(0);
    }
}

struct BlockVertexTree {
    vector<vector<int>> adj;

    template <class G, class = enable_if_t<!is_same_v<BlockVertexTree, remove_cvref_t<G>>>>
    explicit BlockVertexTree(G&& graph) {
        Graph g(forward<G>(graph));
        auto [_, n, map] = g;
        adj.resize(n);

        biconnected_components(
            g, [](auto) {},
            [&, &map = map](auto it, auto it_end) {
                int vc = sz(adj);
                adj.emplace_back();
                for (; it != it_end; ++it) {
                    auto [v2, _2] = map(*it->second);
                    for (int v : {it->first, v2})
                        if (!sz(adj[v]) || adj[v].back() != vc)
                            adj[v].push_back(vc), adj[vc].push_back(v);
                }
            });
    }

    bool is_cut(int v) { return sz(adj[v]) == 1; }
};

int main() {
    // int n, m; read(n, m);
    // vector adj(n, vector<pair<int, int>>());
    // rep(i, m) {
    //     int u, v; read(u, v);
    //     adj[u].emplace_back(v, i);
    //     adj[v].emplace_back(u, i);
    // }

    // vector<vector<int>> bicomps;
    // biconnected_components(adj, [](auto&&...) {}, [&](auto it, auto it_end) {
    //     auto& comp = bicomps.emplace_back();
    //     for (; it != it_end; ++it)
    //         comp.push_back(it->second->second);
    // });

    // println(sz(bicomps));
    // trav(comp, bicomps)
    //     println(sz(comp), comp);

    // int n, m; read(n, m);
    // vector adj(n, vector<pair<int, int>>());
    // rep(i, m) {
    //     int u, v; read(u, v);
    //     adj[u].emplace_back(v, i);
    //     adj[v].emplace_back(u, i);
    // }

    // vector is_cut(n, false);
    // biconnected_components(adj, [&](int v) { is_cut[v] = true; }, [](auto&&...) {});

    // rep(i, n)
    //     if (is_cut[i])
    //         println(i);

    int n, m; read(n, m);
    vector w(n, 0);
    read(w);
    vector adj(n, vector<pair<int, int>>());
    rep(i, m) {
        int u, v; read(u, v); --u, --v;
        adj[u].emplace_back(v, i);
        adj[v].emplace_back(u, i);
    }

    BlockVertexTree bvt(adj);
    int nt = sz(bvt.adj);
    vector wsum(nt, 0ll);
    copy(all(w), begin(wsum));
    auto dfs = [&](int v, int p, auto&& self) -> void {
        trav(v2, bvt.adj[v])
            if (v2 != p)
                self(v2, v, self), wsum[v] += wsum[v2];
    };
    dfs(0, -1, dfs);

    rep(i, n) {
        if (bvt.is_cut(i)) {
            println(wsum[0] - w[i]);
            continue;
        }

        ll mx = wsum[0] - wsum[i];
        trav(v, bvt.adj[i])
            if (wsum[v] < wsum[i])
                mx = max(mx, wsum[v]);
        println(mx);
    }
}
accuracy: 1
time_ms: 30
memory_kb: 24644
final_rank: 7

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define int long long
typedef long long ll;
using namespace std;
#define inf 0x3f3f3f3f

const int N = 1E5+100;
int low[N],dfn[N];
int val[N],tot[N];
int p = 0;
int n,m;
int st[N],nxt[N<<1],to[N<<1],e;
int pre[N];
void  addEdge(int u,int v){
    e++;nxt[e] = st[u];st[u] = e;to[e] = v;
    e++;nxt[e] = st[v];st[v] = e;to[e] = u;
}
void init(){
    memset(st,-1,sizeof(st));
    memset(nxt,-1,sizeof(nxt));
}
vector<int> res[N];
void tarjan(int u,int fa){
    low[u] = dfn[u] = ++p;
    tot[u] = val[u];
    pre[u] = fa;
    for(int i = st[u];i!= -1;i = nxt[i]){
            int v = to[i];
            if(!dfn[v]){
                    res[u].push_back(v);
                    tarjan(v,u);
                    tot[u]+=tot[v];
                    low[u] = min(low[u],low[v]);
            }else if(v != fa){
                    low[u] = min(low[u],dfn[v]);
            }
    }
}

signed main(void){
    init();
    cin>>n>>m;
    for(int i = 1;i<=n;i++){
            scanf("%lld",&val[i]);
    }
    int u,v;
    for(int i = 0;i<m;i++){
            scanf("%lld%lld",&u,&v);
            addEdge(u,v);
    }
    for(int i = 1;i<=n;i++){
        if(!dfn[i]){tarjan(i,0);}
    }
    for(int i= 1;i<=n;i++){
            int ans = 0;
            int cur = tot[1]-tot[i];
            int nm = res[i].size();
            for(int j = 0;j<nm;j++){
                    v = res[i][j];
                    if(low[v]<dfn[i]){
                            cur+=tot[v];
                    }else{
                            ans = max(ans,tot[v]);
                    }
            }
            ans = max(ans,cur);
            printf("%lld\n",ans);
    }
    return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 16000
final_rank: 2

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 100005

vector<int> G[SIZE],children[SIZE];
int N;
bool visited[SIZE],is_art[SIZE];
int visited_order[SIZE],parent[SIZE],lowest[SIZE],number;
ll W[SIZE],dp[SIZE];


void dfs(int current_node,int pre_node){
	visited_order[current_node] = lowest[current_node] = number;  //訪問順を記録
	number++;

	visited[current_node] = true;
	dp[current_node] = W[current_node];

	int next;

	for(int i = 0; i < G[current_node].size(); i++){
		next = G[current_node][i];
		if(!visited[next]){
			parent[next] = current_node;
			children[current_node].push_back(next);

			dfs(next,current_node);
			dp[current_node] += dp[next];

			lowest[current_node] = min(lowest[current_node],lowest[next]); //ボトムアップ的に、lowestが求まる
		}else if(visited[next] == true && next != pre_node){ //dfsTreeを遡る場合
			lowest[current_node] = min(lowest[current_node],visited_order[next]);
		}
	}
}

void art_points(){

	for(int i = 0; i < N; i++){

		visited[i] = false;
		is_art[i] = false;
	}

	number = 1;
	dfs(0,-1);

	int tmp_parent,root_num = 0;

	vector<int> V;

	for(int i = 1; i < N; i++){
		tmp_parent = parent[i];
		if(tmp_parent == 0){
			root_num++;
		}else if(visited_order[tmp_parent] <= lowest[i]){
			V.push_back(tmp_parent);
		}
	}
	if(root_num >= 2){
		V.push_back(0);
	}
	sort(V.begin(),V.end());
	V.erase(unique(V.begin(),V.end()),V.end());

	for(int i = 0; i < V.size(); i++){

		is_art[V[i]] = true;
	}
}


int main(){
	int E;

	scanf("%d %d",&N,&E);

	ll SUM = 0;

	for(int i = 0; i < N; i++){

		scanf("%lld",&W[i]);
		SUM += W[i];
	}

	int from,to;

	for(int i = 0; i < E; i++){
		scanf("%d %d",&from,&to);
		from--;
		to--;
		G[from].push_back(to);
		G[to].push_back(from);
	}

	art_points();

	for(int i = 0; i < N; i++){

		if(!is_art[i]){

			printf("%lld\n",SUM-W[i]);
			continue;
		}

		ll ans = 0;

		if(i == 0){

			for(int k = 0; k < G[i].size(); k++){

				ans = max(ans,dp[G[i][k]]);
			}

		}else{

			ll sum_P = SUM-dp[i];

			for(int k = 0; k < children[i].size(); k++){

				int child = children[i][k];

				if(lowest[child] < visited_order[i]){ //親と連結している子

					sum_P += dp[child];
				}else{
					ans = max(ans,dp[child]);
				}
			}

			ans = max(ans,sum_P);
		}

		printf("%lld\n",ans);
	}

	return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 15984
final_rank: 4

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 100000


int N,E;
bool visited[SIZE],is_art_point[SIZE];
int visited_order[SIZE],parent[SIZE],lowest[SIZE],number;
ll W[SIZE],dp[SIZE];
vector<int> G[SIZE],children[SIZE];


void dfs(int current_node,int pre_node){
	visited_order[current_node] = lowest[current_node] = number;  //訪問順を記録
	number++;

	visited[current_node] = true;
	dp[current_node] = W[current_node];

	int next;

	for(int i = 0; i < G[current_node].size(); i++){
		next = G[current_node][i];
		if(!visited[next]){
			parent[next] = current_node;
			dfs(next,current_node);

			dp[current_node] += dp[next];
			children[current_node].push_back(next);

			lowest[current_node] = min(lowest[current_node],lowest[next]); //ボトムアップ的に、lowestが求まる
		}else if(visited[next] == true && next != pre_node){ //dfsTreeを遡る場合
			lowest[current_node] = min(lowest[current_node],visited_order[next]);
		}
	}
}

void art_points(){

	for(int i = 0; i < N; i++){

		visited[i] = false;
		is_art_point[i] = false;
		dp[i] = 0;
	}

	number = 1;
	dfs(0,-1);

	int tmp_parent,root_num = 0;

	vector<int> V;

	for(int i = 1; i < N; i++){
		tmp_parent = parent[i];
		if(tmp_parent == 0){
			root_num++;
		}else if(visited_order[tmp_parent] <= lowest[i]){
			V.push_back(tmp_parent);
		}
	}
	if(root_num >= 2){
		V.push_back(0);
	}
	sort(V.begin(),V.end());
	V.erase(unique(V.begin(),V.end()),V.end());

	for(int i = 0; i < V.size(); i++){
		//printf("%d\n",V[i]);
		is_art_point[V[i]] = true;
	}
}


int main(){

	scanf("%d %d",&N,&E);

	ll sum = 0;

	for(int i = 0; i < N; i++){

		scanf("%lld",&W[i]);
		sum += W[i];
	}

	int from,to;

	for(int i = 0; i < E; i++){
		scanf("%d %d",&from,&to);
		from--;
		to--;
		G[from].push_back(to);
		G[to].push_back(from);
	}

	art_points();

	for(int i = 0; i < N; i++){

		if(!is_art_point[i]){

			printf("%lld\n",sum-W[i]);
			continue;
		}

		ll ans = 0;

		if(i == 0){

			for(int k = 0; k < children[i].size(); k++){

				int child = children[i][k];
				ans = max(ans,dp[child]);
			}

		}else{

			ll sum_P = sum-dp[i];

			for(int k = 0; k < children[i].size(); k++){

				int child = children[i][k];
				if(lowest[child] < visited_order[i]){ //親の成分と連結している子成分

					sum_P += dp[child];
				}else{

					ans = max(ans,dp[child]);
				}
			}

			ans = max(ans,sum_P);
		}

		printf("%lld\n",ans);
	}

	return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 15996
final_rank: 5