← Home
#include <bits/stdc++.h>
using namespace std;
 
using ll = long long;
 
struct Edge {
    int to;
    int id;
};
 
int n, m, k;
vector<int> special_vertices;
vector<ll> c;
vector<ll> w_edge;
vector<int> U, V;                 // original edges
 
/* ---------- 1. bridges (Tarjan) ---------- */
vector<vector<Edge>> g;
vector<int> tin, low;
vector<char> is_bridge;
int timerDFS = 0;
 
void dfs_bridge(int v, int p_edge) {
    tin[v] = low[v] = ++timerDFS;
    for (auto e : g[v]) {
        if (e.id == p_edge) continue;
        int to = e.to;
        if (tin[to]) {
            low[v] = min(low[v], tin[to]);
        } else {
            dfs_bridge(to, e.id);
            low[v] = min(low[v], low[to]);
            if (low[to] > tin[v]) {
                is_bridge[e.id] = 1;
            }
        }
    }
}
 
/* ---------- 2. DSU for components ---------- */
struct DSU {
    vector<int> p, sz;
    DSU(int n = 0) { init(n); }
    void init(int n) {
        p.resize(n);
        sz.assign(n, 1);
        iota(p.begin(), p.end(), 0);
    }
    int find(int x) { return p[x] == x ? x : p[x] = find(p[x]); }
    void unite(int a, int b) {
        a = find(a); b = find(b);
        if (a == b) return;
        if (sz[a] < sz[b]) swap(a, b);
        p[b] = a;
        sz[a] += sz[b];
    }
};
 
/* ---------- 3. tree DP ---------- */
struct TreeEdge {
    int to;
    ll w;
    bool critical;          // separates specials
};
 
int Ncomp;                          // number of components
vector<ll> compVal;                 // sum of c_i
vector<int> compSpec;               // 0/1
vector<vector<TreeEdge>> tree;
vector<int> subSpec;                // number of special components in subtree
vector<ll> dp;                      // profit of subtree
vector<char> hasSpecialComp;        // bool per component
ll totalSpec;
 
/* first DFS – compute subSpec and dp */
void dfs1(int v, int parent, ll wpar, bool critpar) {
    subSpec[v] = compSpec[v];
    ll sum = compVal[v];
    for (auto &e : tree[v]) {
        if (e.to == parent) continue;
        dfs1(e.to, v, e.w, e.critical);
        subSpec[v] += subSpec[e.to];
        ll gain = dp[e.to];
        if (e.critical) gain -= e.w;
        if (gain < 0) gain = 0;
        sum += gain;
    }
    dp[v] = sum;
}
 
/* second DFS – reroot and compute answer for every component */
vector<ll> answerComp;
 
void dfs2(int v, int parent,
          ll upProfitSide,          // profit of the rest of the tree (excluding subtree v)
          ll wpar, bool critpar) {
    // contribution from parent side to v
    ll contribParent = 0;
    if (parent != -1) {
        ll tmp = upProfitSide;
        if (critpar) tmp -= wpar;
        if (tmp < 0) tmp = 0;
        contribParent = tmp;
    }
 
    // compute answer for v
    ll ans = compVal[v] + contribParent;
    // store contributions of children for later prefix/suffix sums
    int deg = tree[v].size();
    vector<ll> childContrib;
    childContrib.reserve(deg);
    vector<int> childs;
    childs.reserve(deg);
    for (auto &e : tree[v]) {
        if (e.to == parent) continue;
        ll gain = dp[e.to];
        if (e.critical) gain -= e.w;
        if (gain < 0) gain = 0;
        childContrib.push_back(gain);
        childs.push_back(e.to);
        ans += gain;
    }
    answerComp[v] = ans;
 
    // prefix sums of child contributions to obtain rest profit quickly
    int sz = childContrib.size();
    vector<ll> pref(sz + 1, 0), suff(sz + 1, 0);
    for (int i = 0; i < sz; ++i) pref[i + 1] = pref[i] + childContrib[i];
    for (int i = sz - 1; i >= 0; --i) suff[i] = suff[i + 1] + childContrib[i];
 
    // go to children
    for (int idx = 0; idx < sz; ++idx) {
        int to = childs[idx];
        // profit of the rest of the tree when edge v‑to is cut
        ll rest = compVal[v] + contribParent + pref[idx] + suff[idx + 1];
        // pass it to child
        // find the edge data to know weight and critical flag
        ll w = 0; bool crit = false;
        for (auto &e : tree[v]) if (e.to == to) { w = e.w; crit = e.critical; break; }
        dfs2(to, v, rest, w, crit);
    }
}
 
/* ---------- main ---------- */
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cin >> n >> m >> k;
    special_vertices.resize(k);
    for (int i = 0; i < k; ++i) {
        cin >> special_vertices[i];
        --special_vertices[i];
    }
    c.resize(n);
    for (int i = 0; i < n; ++i) cin >> c[i];
    w_edge.resize(m);
    for (int i = 0; i < m; ++i) cin >> w_edge[i];
    U.resize(m);
    V.resize(m);
    g.assign(n, {});
    for (int i = 0; i < m; ++i) {
        int x, y;
        cin >> x >> y;
        --x; --y;
        U[i] = x; V[i] = y;
        g[x].push_back({y, i});
        g[y].push_back({x, i});
    }
 
    /* bridges */
    tin.assign(n, 0);
    low.assign(n, 0);
    is_bridge.assign(m, 0);
    for (int i = 0; i < n; ++i)
        if (!tin[i]) dfs_bridge(i, -1);
 
    /* components */
    DSU dsu(n);
    for (int i = 0; i < m; ++i)
        if (!is_bridge[i])
            dsu.unite(U[i], V[i]);
 
    vector<int> compId(n);
    unordered_map<int,int> mapId; // root -> 0..Ncomp-1
    Ncomp = 0;
    for (int i = 0; i < n; ++i) {
        int r = dsu.find(i);
        auto it = mapId.find(r);
        if (it == mapId.end()) {
            mapId[r] = Ncomp++;
        }
        compId[i] = mapId[r];
    }
 
    compVal.assign(Ncomp, 0);
    compSpec.assign(Ncomp, 0);
    for (int i = 0; i < n; ++i) {
        int id = compId[i];
        compVal[id] += c[i];
    }
    for (int v : special_vertices) {
        compSpec[compId[v]] = 1;
    }
 
    /* build bridge tree */
    tree.assign(Ncomp, {});
    for (int i = 0; i < m; ++i) if (is_bridge[i]) {
        int a = compId[U[i]];
        int b = compId[V[i]];
        ll w = w_edge[i];
        tree[a].push_back({b, w, false}); // critical will be set later
        tree[b].push_back({a, w, false});
    }
 
    /* total number of special components */
    totalSpec = 0;
    for (int i = 0; i < Ncomp; ++i) if (compSpec[i]) ++totalSpec;
 
    /* compute subSpec to know which bridges are critical */
    subSpec.assign(Ncomp, 0);
    function<void(int,int)> dfsCount = [&](int v, int p){
        subSpec[v] = compSpec[v];
        for (auto &e : tree[v]) if (e.to != p) {
            dfsCount(e.to, v);
            subSpec[v] += subSpec[e.to];
        }
    };
    dfsCount(0, -1);
    // set critical flag
    for (int v = 0; v < Ncomp; ++v) {
        for (auto &e : tree[v]) {
            if (e.critical) continue; // already set from other side
            // we need subSpec of the side that is e.to's subtree
            // we have it because we performed dfsCount with root 0
            // Determine which side is child
            // If subSpec[e.to] < subSpec[v] then e.to is child, else v is child
            int child = e.to;
            int parent = v;
            // ensure child is the deeper node in the rooted tree (0 as root)
            // we can compare depths using subSpec, but safer to store parent during dfsCount.
        }
    }
    // To know parent direction we redo dfs with parent array
    vector<int> parent(Ncomp, -1);
    vector<ll> weightToParent(Ncomp, 0);
    function<void(int,int)> dfsParent = [&](int v, int p){
        for (auto &e : tree[v]) if (e.to != p) {
            parent[e.to] = v;
            weightToParent[e.to] = e.w;
            dfsParent(e.to, v);
        }
    };
    dfsParent(0, -1);
    // now set critical flag for each edge (once)
    for (int v = 1; v < Ncomp; ++v) {
        int p = parent[v];
        ll w = weightToParent[v];
        bool critical = (subSpec[v] > 0 && totalSpec - subSpec[v] > 0);
        // set in both adjacency lists
        for (auto &e : tree[v]) if (e.to == p) { e.critical = critical; e.w = w; }
        for (auto &e : tree[p]) if (e.to == v) { e.critical = critical; e.w = w; }
    }
 
    /* DP on tree */
    dp.assign(Ncomp, 0);
    dfs1(0, -1, 0, false);
 
    answerComp.assign(Ncomp, 0);
    dfs2(0, -1, 0, 0, false);
 
    /* output for original vertices */
    for (int i = 0; i < n; ++i) {
        if (i) cout << ' ';
        cout << answerComp[ compId[i] ];
    }
    cout << '\n';
    return 0;
}