This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
// Hallelujah, praise the one who set me free
// Hallelujah, death has lost its grip on me
// You have broken every chain, There's salvation in your name
// Jesus Christ, my living hope
#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <utility>
#include <numeric>
#include <bitset>
#include <map>
#include <queue>
#include <cassert>
using namespace std;
#define REP(i, s, e) for (int i = (s); i < (e); i++)
#define RREP(i, s, e) for (int i = (s); i >= (e); i--)
template <class T>
inline bool mnto(T& a, T b) {return a > b ? a = b, 1 : 0;}
template <class T>
inline bool mxto(T& a, T b) {return a < b ? a = b, 1: 0;}
typedef unsigned long long ull;
typedef long long ll;
typedef long double ld;
#define FI first
#define SE second
typedef pair<int, int> ii;
typedef pair<ll, ll> pll;
typedef tuple<int, int, int> iii;
typedef tuple<ll, ll, ll> lll;
#define ALL(_a) _a.begin(), _a.end()
#define SZ(_a) (int) _a.size()
#define pb push_back
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<ii> vii;
typedef vector<iii> viii;
#ifndef DEBUG
#define cerr if (0) cerr
#endif
const int INF = 1000000005;
const ll LINF = 1000000000000000005ll;
const int MAXN = 50005;
const int BLK = 300;
//const int MAXN = 50;
//const int BLK = 1;
int n, m, k;
vi adj[MAXN];
string s;
int x[MAXN];
namespace SmallKSolver {
ll base[MAXN], delta[MAXN];
int rawd[MAXN], goodd[MAXN];
ll d[2][MAXN];
queue<int> qu;
deque<int> dq;
priority_queue<lll, vector<lll>, greater<lll>> pq;
bool fix[MAXN];
ll ans[MAXN];
int main() {
// distance to closest stop
REP (i, 0, n) {
rawd[i] = INF;
}
REP (i, 0, n) {
if (s[i] == '1') {
qu.push(i);
rawd[i] = 0;
}
}
while (!qu.empty()) {
int u = qu.front(); qu.pop();
for (int v : adj[u]) {
if (mnto(rawd[v], rawd[u] + 1)) {
qu.push(v);
}
}
}
REP (i, 0, n) {
if (rawd[i] == 0) {
rawd[i] = 2;
}
}
REP (i, 1, k) {
base[0] += rawd[x[i]];
}
// "good" vertex is stop cell and has adjacent stop cell
// distance to closest "good" vertex
REP (i, 0, n) {
goodd[i] = INF;
}
REP (i, 0, n) {
if (s[i] == '0') {
continue;
}
bool gd = 0;
for (int v : adj[i]) {
if (s[v] == '1') {
gd = 1;
break;
}
}
if (gd) {
goodd[i] = 0;
dq.push_back(i);
}
}
while (!dq.empty()) {
int u = dq.front(); dq.pop_front();
for (int v : adj[u]) {
if (mnto(goodd[v], goodd[u] + (s[u] == '0'))) {
if (s[u] == '0') {
dq.push_back(v);
} else {
dq.push_front(v);
}
}
}
}
REP (i, 1, k) {
delta[i - 1] = goodd[x[i]] - rawd[x[i]];
}
sort(delta, delta + k - 1);
cerr << base[0] << '\n';
REP (i, 1, k) {
base[i] = base[i - 1] + delta[i - 1];
cerr << i << ": " << delta[i - 1] << ' ' << base[i] << '\n';
}
// get answer without stop cells
REP (i, 0, n) {
ans[i] = LINF;
}
ans[x[0]] = 0;
qu.push(x[0]);
while (!qu.empty()) {
int u = qu.front(); qu.pop();
for (int v : adj[u]) {
if (mnto(ans[v], ans[u] + 1) && s[v] == '0') {
qu.push(v);
}
}
}
REP (i, 0, n) {
fix[i] = ans[i] != LINF;
}
REP (g, 0, k) {
cerr << g << '\n';
REP (i, 0, n) {
d[0][i] = d[1][i] = LINF;
}
d[0][x[0]] = 0;
pq.push({0, x[0], 0});
while (!pq.empty()) {
auto [ud, u, t] = pq.top(); pq.pop();
if (d[t][u] != ud) {
continue;
}
for (int v : adj[u]) {
bool b = u != x[0] && s[u] == '1';
if (mnto(d[b | t][v], ud + (b ? 2 * k - 1 - g : 1))) {
pq.push({d[b | t][v], v, b | t});
}
}
}
REP (i, 0, n) {
mnto(ans[i], d[1][i] + base[g] - 2 * (k - 1 - g));
cerr << ' ' << i << ": " << d[i] << ' ' << ans[i] << '\n';
}
}
REP (i, 0, n) {
cout << ans[i] << '\n';
}
return 0;
}
}
namespace BigKSolver {
ll delta[MAXN], cost[MAXN];
int rawd[MAXN], goodd[MAXN];
queue<int> qu;
deque<int> dq;
priority_queue<lll, vector<lll>, greater<lll>> pq;
int mnl[MAXN];
ll d[MAXN][MAXN / BLK + 50];
ll ans[MAXN];
int main() {
int MAXL = n / (k - 1) + 10;
// distance to closest stop
REP (i, 0, n) {
rawd[i] = INF;
}
REP (i, 0, n) {
if (s[i] == '1') {
qu.push(i);
rawd[i] = 0;
}
}
while (!qu.empty()) {
int u = qu.front(); qu.pop();
for (int v : adj[u]) {
if (mnto(rawd[v], rawd[u] + 1)) {
qu.push(v);
}
}
}
// "good" vertex is stop cell and has adjacent stop cell
// distance to closest "good" vertex
REP (i, 0, n) {
goodd[i] = INF;
}
REP (i, 0, n) {
if (s[i] == '0') {
continue;
}
bool gd = 0;
for (int v : adj[i]) {
if (s[v] == '1') {
gd = 1;
break;
}
}
if (gd) {
goodd[i] = 0;
dq.push_back(i);
}
}
while (!dq.empty()) {
int u = dq.front(); dq.pop_front();
for (int v : adj[u]) {
if (mnto(goodd[v], goodd[u] + (s[v] == '0'))) {
if (s[v] == '0') {
dq.push_back(v);
} else {
dq.push_front(v);
}
}
}
}
REP (i, 0, n) {
goodd[i] += s[i] == '1';
}
REP (i, 0, n) {
if (rawd[i] == 0) {
rawd[i] = min(goodd[i], 2);
}
}
ll base = 0;
REP (i, 1, k) {
base += rawd[x[i]];
}
REP (i, 1, k) {
delta[i - 1] = goodd[x[i]] - rawd[x[i]];
cerr << delta[i - 1] << "\n";
}
sort(delta, delta + k - 1);
cost[1] = base;
int ptr = 0;
REP (i, 2, n + 1) {
while (ptr < k - 1 && delta[ptr] <= i - 2) {
ptr++;
}
cost[i] = cost[i - 1] + 2 * (k - 1) - ptr;
cerr << i << ": " << cost[i] << "\n";
}
REP (i, 0, n) {
mnl[i] = INF;
}
mnl[x[0]] = 0;
dq.pb(x[0]);
while (!dq.empty()) {
int u = dq.front(); dq.pop_front();
for (int v : adj[u]) {
bool b = u != x[0] && s[u] == '1';
if (mnto(mnl[v], mnl[u] + b)) {
if (b) {
dq.push_back(v);
} else {
dq.push_front(v);
}
}
}
}
REP (i, 0, n) {
ans[i] = LINF;
REP (j, 0, MAXL) {
d[i][j] = LINF;
}
}
d[x[0]][0] = 0;
pq.push({0, x[0], 0});
while (!pq.empty()) {
auto [ud, u, l] = pq.top(); pq.pop();
if (ud != d[u][l - mnl[u]]) {
continue;
}
for (int v : adj[u]) {
bool b = u != x[0] && s[u] == '1';
if (l + b - mnl[v] < MAXL && mnto(d[v][l + b - mnl[v]], ud + 1)) {
pq.push({d[v][l + b - mnl[v]], v, l + b});
}
}
}
REP (i, 0, n) {
REP (j, 0, min(MAXL, n - mnl[i] + 1)) {
mnto(ans[i], d[i][j] + cost[j + mnl[i]]);
}
}
REP (i, 0, n) {
cout << ans[i] << '\n';
}
return 0;
}
}
int main() {
#ifndef DEBUG
ios::sync_with_stdio(0), cin.tie(0);
#endif
cin >> n >> m >> k;
REP (i, 0, m) {
int u, v; cin >> u >> v;
u--; v--;
adj[u].pb(v);
adj[v].pb(u);
}
cin >> s;
REP (i, 0, k) {
cin >> x[i];
x[i]--;
}
if (k <= BLK) {
return SmallKSolver::main();
} else {
return BigKSolver::main();
}
}
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |