#include<bits/stdc++.h>

#define REP(i,s,n) for(int i=s;i<n;++i)
#define rep(i,n) REP(i,0,n)
#define EPS (1e-8)
#define equals(a,b) (fabs((a)-(b))<EPS)
#define pb push_back
#define ALL(x) x.begin(),x.end()
#define fst first
#define snd second

using namespace std;

typedef long long ll;

bool LT(double a,double b) { return !equals(a,b) && a < b; }
bool LTE(double a,double b) { return equals(a,b) || a < b; }

typedef pair<int,int> ii;
struct Edge { int src,dst,w; };
const int MAX_V = 1000100; //
int V,E; //
vector<Edge> G[MAX_V]; // undirected graph
vector<int> dfs_num,dfs_low,dfs_parent,articulation_vertex;
int dfsNumberCounter, dfsRoot, rootChildren;

set<ii> bridges;
#define UNVISITED -1
void articulationPointAndBridge(int u){
  dfs_low[u] = dfs_num[u] = dfsNumberCounter++;
  rep(j,(int)G[u].size()){
    Edge &v = G[u][j];
    if( dfs_num[v.dst] == UNVISITED ) {
      dfs_parent[v.dst] = u;
      if( u == dfsRoot ) rootChildren++;

      articulationPointAndBridge(v.dst);

      if( dfs_low[v.dst] >= dfs_num[u] ) articulation_vertex[u] = true;
      if( dfs_low[v.dst] >  dfs_num[u] ) {
        //printf("Edge (%d,%d) is a bridge\n",u,v.dst);
	int s = u, t = v.dst;
	if( s > t ) swap(s,t);
	bridges.insert(ii(s,t));
      }
      dfs_low[u] = min(dfs_low[u],dfs_low[v.dst]);
    } else if( v.dst != dfs_parent[u] ) {
      dfs_low[u] = min(dfs_low[u],dfs_num[v.dst]);
    }
  }
}

void calculateArticulationPointAndBridge(){
  dfsNumberCounter = 0;
  dfs_num.assign(V,UNVISITED);
  dfs_low.assign(V,0);
  dfs_parent.assign(V,0);
  articulation_vertex.assign(V,0);
  
  //printf("Bridges:\n");
  rep(i,V) {
    if( dfs_num[i] == UNVISITED ) {
      dfsRoot = i, rootChildren = 0;
      articulationPointAndBridge(i);
      articulation_vertex[dfsRoot] = ( rootChildren > 1 );
    }
  }
  
  //printf("Articulation Points:\n");
  //rep(i,V) if( articulation_vertex[i] ) printf("Vertex %d\n",i);
}


vector<int> T[MAX_V];
int par[MAX_V];
int tdfs(int cur,int id,vector<int> &w) {
  int score = w[cur];
  rep(i,(int)G[cur].size()) {
    int dst = G[cur][i].dst;
    int s = cur, t = dst;
    if( s > t ) swap(s,t);
    if( bridges.count(ii(s,t)) ) continue;
    if( par[dst] != -1 ) {
      assert( par[dst] == id );
      continue;
    }
    par[dst] = id;
    score += tdfs(dst,id,w);
  }
  return score;
}

const bool debug = 0;
vector<bool> isLoop;
/*
ll mdfs(int cur,int prev, vector<int> &w) {
  ll maxi = w[cur];
  rep(i,(int)T[cur].size()) {
    int nex = T[cur][i];
    if( nex == prev ) continue;
    ll score = mdfs(nex,cur,w) + (ll)w[cur];
    maxi = max(maxi,score);
  }
  return maxi;
}
*/
ii mdfs(int cur,int prev,vector<int> &w) {
  ii ret = ii(0,0);
  bool loop = isLoop[cur];
  rep(i,(int)T[cur].size()) {
    int nex = T[cur][i];
    if( nex == prev ) continue;
    ii tmp = mdfs(nex,cur,w);
    if( tmp.fst > 0 ) loop = true;
    ret.fst += tmp.fst;
    ret.snd = max(ret.snd, tmp.snd);
  }
  if( loop ) {
    ret.fst += w[cur];
  } else {
    ret.snd += w[cur];
  }
  return ret;
}

void compute(vector<int> &ow) {
  calculateArticulationPointAndBridge();
  memset(par,-1,sizeof par);
  int nV = 0;
  vector<int> w;
  rep(i,V) {
    if( par[i] == -1 ) {
      par[i] = nV;
      int cost = tdfs(i,nV++,ow);
      w.pb(cost);
    }
  }
  map<int,int> mp;
  rep(i,V)  ++mp[par[i]];
  rep(i,nV) isLoop.pb(mp[i]>1);
  
  if( debug ) {
    cout << "nV = " << nV << endl;
    rep(i,nV) {
      cout << i << "-th: w[" << i << "] = " << w[i]  << endl;
    }
    cout << "--" << endl;
    rep(i,V) {
      cout << i << "-th: par[" << i << "] = " << par[i] << endl;
    }
  }

  set<ii> added;
  rep(i,V) {
    int src = par[i];
    rep(j,(int)G[i].size()) {
      int dst = par[G[i][j].dst];
      if( src == dst ) continue;
      if( added.count(ii(src,dst)) ) continue;
      added.insert(ii(src,dst));
      added.insert(ii(dst,src));
      T[src].pb(dst);
      T[dst].pb(src);
    }
  }

  if( debug ) {
    cout << "Tree ---" << endl;
    rep(i,nV) {
      cout << "* " << i << "-th:" << endl;
      rep(j,(int)T[i].size()) {
	cout << T[i][j] << " ";
      } puts("");
    }
  }
  ii tmp = mdfs(par[0],-1,w);
  cout << tmp.fst + tmp.snd << endl;
  
}

int main() {
  int s, t;
  cin >> V >> E;
  vector<int> w(V);
  rep(i,V) cin >> w[i];
  rep(i,E) {
    cin >> s >> t;
    --s, --t;
    G[s].pb((Edge){s,t,0});
    G[t].pb((Edge){t,s,0});
  }
  compute(w);
  return 0;
}



Measured memory_bytes: 90400