The competitors of Bubble Cup X gathered after the competition and discussed what is the best way to get to know the host country and its cities.
After exploring the map of Serbia for a while, the competitors came up with the following facts: the country has V cities which are indexed with numbers from 1 to V, and there are E bi-directional roads that connect the cites. Each road has a weight (the time needed to cross that road). There are N teams at the Bubble Cup and the competitors came up with the following plan: each of the N teams will start their journey in one of the V cities, and some of the teams share the starting position.
They want to find the shortest time T, such that every team can move in these T minutes, and the number of different cities they end up in is at least K (because they will only get to know the cities they end up in). A team doesn’t have to be on the move all the time, if they like it in a particular city, they can stay there and wait for the time to pass.
Please help the competitors to determine the shortest time T so it’s possible for them to end up in at least K different cities or print -1 if that is impossible no matter how they move.
Note that there can exist multiple roads between some cities.
Input
The first line contains four integers: V, E, N and K (1 ≤ V ≤ 600, 1 ≤ E ≤ 20000, 1 ≤ N ≤ min(V, 200), 1 ≤ K ≤ N), number of cities, number of roads, number of teams and the smallest number of different cities they need to end up in, respectively.
The second line contains N integers, the cities where the teams start their journey.
Next E lines contain information about the roads in following format: A i B i T i (1 ≤ A i, B i ≤ V, 1 ≤ T i ≤ 10000), which means that there is a road connecting cities A i and B i, and you need T i minutes to cross that road.
Output
Output a single integer that represents the minimal time the teams can move for, such that they end up in at least K different cities or output -1 if there is no solution.
If the solution exists, result will be no greater than 1731311.
Example
input
6 7 5 4
5 5 2 2 5
1 3 3
1 5 2
1 6 5
2 5 4
2 6 7
3 4 11
3 5 3
output
3
Note
Three teams start from city 5, and two teams start from city 2. If they agree to move for 3 minutes, one possible situation would be the following: Two teams in city 2, one team in city 5, one team in city 3 , and one team in city 1. And we see that there are four different cities the teams end their journey at.
#include <bits/stdc++.h>
using namespace std;
template <class T> class flow_graph {
public:
static constexpr T eps = (T) 1e-9;
struct edge {
int to;
T c;
T f;
int rev;
};
vector < vector <edge> > g;
vector <int> ptr;
vector <int> d;
int n;
int st, fin;
bool modified;
flow_graph(int n, int st, int fin) : n (n), st (st), fin (fin) {
modified = true;
assert(0 <= st && st < n && 0 <= fin && fin < n && st != fin);
g.resize(n);
ptr.resize(n);
d.resize(n);
}
void clear_flow() {
modified = true;
for (int i = 0; i < n; i++) {
for (edge &e : g[i]) {
e.f = 0;
}
}
}
void add(int from, int to, T forward_cap, T backward_cap) {
modified = true;
assert(0 <= from && from < n && 0 <= to && to < n);
int from_size = g[from].size();
int to_size = g[to].size();
g[from].push_back({to, forward_cap, 0, to_size});
g[to].push_back({from, backward_cap, 0, from_size});
}
bool expath() {
queue <int> q({st});
fill(d.begin(), d.end(), -1);
d[st] = 0;
while (!q.empty()) {
int i = q.front();
q.pop();
for (edge &e : g[i]) {
if (e.c > e.f + eps && d[e.to] == -1) {
d[e.to] = d[i] + 1;
if (e.to == fin) {
return true;
}
q.push(e.to);
}
}
}
return false;
}
T dfs(int v, T w) {
if (v == fin) {
return w;
}
T r = 0;
int j = ptr[v];
while (j > 0) {
j--;
edge &e = g[v][j];
if (e.c > e.f + eps && d[e.to] == d[v] + 1) {
T ww = e.c - e.f;
if (v != st) {
ww = min(ww, w - r);
}
T t = dfs(e.to, ww);
if (t > 0) {
e.f += t;
g[e.to][e.rev].f -= t;
r += t;
if (v != st && r >= w - eps) {
return r;
}
}
}
ptr[v]--;
}
return r;
}
T flow;
T max_flow() {
if (!modified) {
return flow;
}
modified = false;
T ans = 0;
while (expath()) {
for (int i = 0; i < n; i++) {
ptr[i] = g[i].size();
}
T add = dfs(st, -1);
if (add <= eps) {
break;
}
ans += add;
}
return flow = ans;
}
vector <bool> min_cut() {
max_flow();
vector <bool> ret(n);
for (int i = 0; i < n; i++) {
ret[i] = (d[i] != -1);
}
return ret;
}
};
const int N = 1234;
int city[N];
int g[N][N];
int main() {
int v, e, n, k;
scanf("%d %d %d %d", &v, &e, &n, &k);
for (int i = 0; i < n; i++) {
scanf("%d", city + i);
city[i]--;
}
for (int i = 0; i < v; i++) {
for (int j = 0; j < v; j++) {
g[i][j] = (i == j ? 0 : (int) 1e9);
}
}
for (int i = 0; i < e; i++) {
int x, y, z;
scanf("%d %d %d", &x, &y, &z);
x--; y--;
g[x][y] = min(g[x][y], z);
g[y][x] = min(g[y][x], z);
}
for (int k = 0; k < v; k++) {
for (int i = 0; i < v; i++) {
for (int j = 0; j < v; j++) {
g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
}
}
}
const int inf = (int) 2e6;
int low = 0, high = inf;
while (low < high) {
int mid = (low + high) >> 1;
flow_graph <int> gr(n + v + 2, n + v, n + v + 1);
for (int i = 0; i < n; i++) {
gr.add(n + v, i, 1, 0);
}
for (int j = 0; j < v; j++) {
gr.add(n + j, n + v + 1, 1, 0);
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < v; j++) {
if (g[city[i]][j] <= mid) {
gr.add(i, n + j, 1, 0);
}
}
}
if (gr.max_flow() >= k) {
high = mid;
} else {
low = mid + 1;
}
}
printf("%d\n", low == inf ? -1 : low);
return 0;
}