Problem:
Escape

頂点に正の値を持つ無向グラフが与えられる。
頂点には 1 から N の番号がついており、i 番目の頂点は w_i の値を持っている。
1 番目の頂点からスタートし、直前に通った辺を通ることができないという制約のもとでグラフ上を移動することができる。
各頂点では，初めて訪れた時に限りその頂点が持つ値の点数を得られる。

取得できる点数の総和の最大値を求めよ。

Constraints

1 ≤ N ≤ 100000

N − 1 ≤ M ≤ 100000

1 ≤ w_i ≤ 1000

1 ≤ u_i, v_i ≤ N

多重辺・自己辺は存在しない

グラフは連結である

Input Format

入力は以下の形式で標準入力から与えられる。

N M
w_1 w_2 ... w_N
u_1 v_1
u_2 v_2
...
u_M v_M

1 行目にはグラフの頂点数 N と辺の数を表す整数 M が入力される。

2 行目には各頂点が持つ値 w_i が入力される。

さらに続けて M 行に、各辺により繋がれる 2 頂点の番号が入力される。

Output Format

答えを1行に出力せよ。

Sample Input 1

6 6
1 2 3 4 5 6
1 2
2 3
3 4
1 4
4 5
5 6

Sample Output 1

21

頂点 1→2→3→4→5→6 と進むことで全ての頂点の点数を集めることができます。

Sample Input 2

7 8
1 3 3 5 2 2 3
1 2
2 3
3 1
1 4
1 7
1 5
1 6
5 6

Sample Output 2

16

頂点 1→2→3→1→5→6→1→4 と進むことで16点を集めることができます。

Solution in C++11 (judge verdict: Runtime Error)

#include <bits/stdc++.h>

using namespace std;

#define int long long
#define all(v) begin(v), end(v)
#define rep(i, n) for(int i = 0; i < (int)(n); i++)
#define reps(i, s, n) for(int i = (int)(s); i < (int)(n); i++)

template<class T1, class T2> void chmin(T1 &a, T2 b){if(a>b)a=b;}
template<class T1, class T2> void chmax(T1 &a, T2 b){if(a<b)a=b;}

using pint = pair<int, int>;
using tint = tuple<int, int, int>;
using vint = vector<int>;

const int inf = 1LL << 55;
const int mod = 1e9 + 7;

struct UnionFind {
  vector<int> data;
  UnionFind(){}
  UnionFind(int sz):data(sz, -1){}
  int find(int x) {
    return data[x] < 0 ? x : data[x] = find(data[x]);
  }
  int size(int x) {
    return -data[find(x)];
  }
  bool same(int x, int y) {
    return find(x) == find(y);
  }
  bool unite(int x, int y) {
    x = find(x), y = find(y);
    if(x == y) return false;
    if(data[x] < data[y]) swap(x, y);
    data[x] += data[y];
    data[y] = x;
    return true;
  }
};

#define MAX_N 100000

int N, M;
int w[MAX_N];
vector<int> graph[MAX_N];

UnionFind uf;
vector< pair<int, int> > edges;
bool vis[MAX_N];
int ord[MAX_N], low[MAX_N], cmp[MAX_N];
vector<int> tree[MAX_N];

int val[MAX_N];
int sz[MAX_N];

void dfs(int u, int p, int &k) {
  vis[u] = true;
  ord[u] = low[u] = k++;
  for(int v : graph[u]) {
    if(!vis[v]) {
      dfs(v, u, k);
      chmin(low[u], low[v]);
      if(ord[u] >= low[v]) uf.unite(u, v);
    } else if(v != p) {
      chmin(low[u], ord[v]);
    }
  }
}

void compose() {
  int k = 0;
  uf = UnionFind(N);
  dfs(0, -1, k);
  int num = 0, conn[MAX_N];
  rep(u, N) if(u == uf.find(u)) conn[u] = num++;
  rep(u, N) cmp[u] = conn[uf.find(u)];
  for(auto e : edges) {
    int x = cmp[e.first], y = cmp[e.second];
    if(x == y) continue;
    tree[x].push_back(y);
    tree[y].push_back(x);
  }
}

int dp1[MAX_N]; // modoreru
int dp2[MAX_N]; // modoranai

int solve(int u, int p) {
  int res = 0;
  for(int v : tree[u]) {
    if(v == p) continue;
    chmax(res, solve(v, u));
    dp1[u] += dp1[v];
  }
  if(sz[u] >= 3 || dp1[u] > 0) dp1[u] += val[u];
  res += val[u];
  for(int v : tree[u]) {
    if(v == p) continue;
    chmax(res, dp1[u]-dp1[v]+dp2[v]);
  }
  return dp2[u] = res;
}

signed main()
{
  cin.tie(0);
  ios_base::sync_with_stdio(0);
  cout << fixed << setprecision(12);

  cin >> N >> M;
  rep(i, N) cin >> w[i];
  rep(i, M) {
    int u, v;
    cin >> u >> v; --u, --v;
    graph[u].push_back(v);
    graph[v].push_back(u);
    edges.emplace_back(minmax(u, v));
  }
  compose();
  rep(u, N) {
    val[cmp[u]] += w[u];
    sz[cmp[u]] = uf.size(u);
  }
  cout << solve(cmp[0], -1) << endl;

  return 0;
}