#include <bits/stdc++.h>
using namespace std;
#define int long long
const int INF = 1e18;
int n,m,k;
vector<int> con[50005];
bool iss[50005];
int init[50005];
int rez[50005];
int dist1[50005];
void calc_closest1()
{
deque<int> dq;
for(int i=1;i<=n;i++)
{
if(iss[i])
{
dist1[i] = 0;
dq.push_back(i);
}
else
{
dist1[i] = INF;
}
}
while(!dq.empty())
{
int nod = dq.front();
dq.pop_front();
for(int adj:con[nod])
{
if(dist1[adj] > dist1[nod] + 1)
{
dist1[adj] = dist1[nod] + 1;
dq.push_back(adj);
}
}
}
}
int best11[50005];
void calc_11()
{
deque<int> dq;
for(int i=1;i<=n;i++)
{
best11[i] = INF;
if(!iss[i])
continue;
bool bun = 0;
for(int adj:con[i])
if(iss[adj])
bun = 1;
if(bun)
{
best11[i] = -1;
dq.push_back(i);
}
}
while(!dq.empty())
{
int nod = dq.front();
dq.pop_front();
for(int adj:con[nod])
{
if(iss[adj])
{
if(best11[adj] > best11[nod])
{
best11[adj] = best11[nod];
dq.push_front(adj);
}
}
else
{
if(best11[adj] > best11[nod] + 1)
{
best11[adj] = best11[nod] + 1;
dq.push_back(adj);
}
}
}
}
for(int i=1;i<=n;i++)
if(iss[i] && best11[i] < INF)
best11[i]++;
}
int direct[50005];
void calc_directly()//see if we can reach some nodes without going through stop nodes
{
deque<int> dq;
for(int i=1;i<=n;i++)
direct[i] = INF;
direct[init[1]] = 0;
dq.push_back(init[1]);
while(!dq.empty())
{
int nod = dq.front();
dq.pop_front();
for(int adj:con[nod])
{
if(!iss[adj] && direct[adj] > direct[nod] + 1)
{
direct[adj] = direct[nod] + 1;
dq.push_back(adj);
}
}
}
for(int i=1;i<=n;i++)
for(int adj:con[i])
rez[adj] = min(rez[adj], direct[i] + 1);
for(int i=1;i<=n;i++)
rez[i] = min(rez[i], direct[i]);
}
int dist[50005];
void calc_dist(int cost_first, int stop_cost)//optimize with 2 queues instead of a pq-------------------------------------------
{
for(int i=1;i<=n;i++)
dist[i] = INF;
for(int i=1;i<=n;i++)
{
if(direct[i] == INF)
continue;
for(int adj:con[i])
{
if(iss[adj])
{
dist[adj] = min(dist[adj], cost_first + (direct[i] + 1));
}
}
}
deque<int> dq, dq2;
for(int i=1;i<=n;i++)
if(dist[i] < INF)
dq.push_back(i);
while(!dq.empty() || !dq2.empty())
{
int nod = -1;
if(!dq.empty() && (dq2.empty() || dist[dq.front()] <= dist[dq2.front()]))
{
nod = dq.front();
dq.pop_front();
}
else
{
assert(!dq2.empty());
nod = dq2.front();
dq2.pop_front();
}
for(int adj:con[nod])
{
if(iss[adj])
{
rez[adj] = min(rez[adj], dist[nod] + 1);
if(dist[adj] > dist[nod] + stop_cost)
{
dist[adj] = dist[nod] + stop_cost;
dq2.push_back(adj);
}
}
else
{
if(dist[adj] > dist[nod] + 1)
{
dist[adj] = dist[nod] + 1;
dq.push_back(adj);
}
}
}
}
for(int i=1;i<=n;i++)
rez[i] = min(rez[i], dist[i]);
}
void solve_small_k()
{
//for(int i=1;i<=n;i++) cerr<<i<<": "<<dist1[i]<<" "<<best11[i]<<" dist1 & best11\n";
//fix the nr of people that use 11------------------------------------
vector<pair<int,int>> ord;
for(int i=2;i<=k;i++)
{
ord.push_back({best11[init[i]] - dist1[init[i]], init[i]});
}
sort(ord.begin(), ord.end());
for(int nr11=0;nr11<=k-1;nr11++)
{
int cost_first = 0, stop_cost = 1;
bool good = 1;
for(int i=0;i<nr11;i++)//take these as 11
{
int x = ord[i].second;
if(best11[x] == INF)
{
good = 0;
break;
}
cost_first += best11[x] + 1;
stop_cost += 1;
}
for(int i=nr11;i<ord.size();i++)//take these as 1
{
int x = ord[i].second;
if(dist1[x] == INF)
{
good = 0;
break;
}
cost_first += dist1[x];
stop_cost += 2;
}
if(good)
{
//cerr<<cost_first<<" "<<stop_cost<<" costs\n";
calc_dist(cost_first, stop_cost);
}
}
}
int min1[50005];
void calc_min1()
{
deque<int> dq;
for(int i=1;i<=n;i++)
min1[i] = INF;
min1[init[1]] = 0;
dq.push_back(init[1]);
while(!dq.empty())
{
int nod = dq.front();
dq.pop_front();
for(int adj:con[nod])
{
if(iss[adj])
{
if(min1[adj] > min1[nod] + 1)
{
min1[adj] = min1[nod] + 1;
dq.push_back(adj);
}
}
else
{
if(min1[adj] > min1[nod])
{
min1[adj] = min1[nod];
dq.push_front(adj);
}
}
}
}
}
map<int,int> dp[50005];
void solve_big_k()
{
int DIF = m / k + 5;
priority_queue<pair<int,pair<int,int>>> pq;
dp[init[1]][0] = -INF;
pq.push({-dp[init[1]][0], {init[1], 0}});
while(!pq.empty())
{
int nod = pq.top().second.first;
int cnt1 = pq.top().second.second;
int cdp = -pq.top().first;
pq.pop();
if(cdp != dp[nod][cnt1])
continue;
for(int adj:con[nod])
{
if(dp[adj][cnt1 + iss[adj]] > cdp + 1 && (cnt1 + iss[adj]) <= min1[adj] + DIF)
{
dp[adj][cnt1 + iss[adj]] = cdp + 1;
pq.push({-dp[adj][cnt1 + iss[adj]], {adj, cnt1 + iss[adj]}});
}
}
}
vector<int> f(n+2, INF);
for(int x=1;x<=n;x++)
{
f[x] = 0;
for(int i=2;i<=k;i++)
{
f[x] += min(dist1[init[i]] + (x-1) * 2, best11[init[i]] + x);
}
}
for(int i=1;i<=n;i++)
{
for(auto it:dp[i])
{
int cnt1 = it.first;
int mydp = it.second + INF;
if(iss[i])
cnt1--;
if(1 <= cnt1 && cnt1 <= n) rez[i] = min(rez[i], mydp + f[cnt1]);
}
}
}
signed main()
{
ios_base::sync_with_stdio(0);cin.tie(0);
cin>>n>>m>>k;
int u,v;
for(int i=1;i<=m;i++)
{
cin>>u>>v;
con[u].push_back(v);
con[v].push_back(u);
}
string s;
cin>>s;
assert(s.size() == n);
for(int i=0;i<s.size();i++)
{
if(s[i] == '1')
iss[i+1] = 1;
else
iss[i+1] = 0;
}
for(int i=1;i<=k;i++)
cin>>init[i];
for(int i=1;i<=n;i++)
rez[i] = INF;
calc_directly();
calc_11();
calc_closest1();
for(int i=1;i<=n;i++)
if(dist1[i] == 0)
dist1[i] = 2;
if(k <= 500 && 0)
{
solve_small_k();
}
else
{
solve_big_k();
}
for(int i=1;i<=n;i++)
{
assert(rez[i] < INF);
cout<<rez[i]<<"\n";
}
return 0;
}