K-pop
Gym - 102020K
https://vjudge.net/problem/Gym-102020K/origin
//二分+搜索找最大流量,再跑最短路求最小花费
//复杂度是 mlog(prime_cnt) + mlogn
namespace IO {
const int MX = 4e7;
char buf[MX]; int ch, sz;
void begin() {
ch = 0;
sz = fread(buf, 1, MX, stdin);
}
inline bool read(int& t) {
while (ch < sz && buf[ch] != '-' && (buf[ch] < '0' || buf[ch] > '9')) ch++;
if (ch >= sz) return false;
bool flag = 0; if (buf[ch] == '-') flag = 1, ch++;
for (t = 0; ch < sz && '0' <= buf[ch] && buf[ch] <= '9'; ++ch)
t = t * 10 + buf[ch] - '0';
if (flag) t = -t;
return true;
}
}
using namespace IO;
const int maxn = 1e5 + 10;
const int maxm = 5e5 + 10;
int n, m, O, D;
int prime[maxm], pcnt = 0;
bool isprime[maxm * 10];
void get_prime() {
prime[++pcnt] = 0;
prime[++pcnt] = 1;
int up = maxm * 10;
for (int i = 2; i < up; ++i) {
if (!isprime[i]) prime[++pcnt] = i;
for (int j = 3; j <= pcnt && i * prime[j] < up; ++j) {
isprime[i * prime[j]] = 1;
if (i % prime[j] == 0) break;
}
}
}
int head[maxn], to[maxm], nxt[maxm], cost[maxm], ecnt = 0;
inline void add(int u, int v, int w) {
to[++ecnt] = v; nxt[ecnt] = head[u]; cost[ecnt] = w; head[u] = ecnt;
}
struct node {
int u, v, a, p;
bool operator < (const node& b) const {
return a > b.a;
}
}p[maxm];
bool vis[maxn];
void init(int n) {
memset(vis, 0, (n + 1)); ecnt = 0;
memset(head, 0, (n + 1) << 2);
}
bool dfs(int s) {
vis[s] = 1;
for (int i = head[s]; i; i = nxt[i]) {
if (vis[to[i]]) continue;
if (to[i] == D) return 1;
if (dfs(to[i])) return 1;
}
return 0;
}
int Binary() {
int l = 1, r = pcnt, mid;
while (l <= r) {
init(n);
mid = l + r >> 1;
int num = prime[mid];
for (int i = 1; i <= m; ++i)
if (p[i].a >= num) add(p[i].u, p[i].v, p[i].p);
else break;
if (dfs(O)) l = mid + 1;
else r = mid - 1;
}
return prime[l - 1];
}
ll dis[maxn];
void dij(int s) {
priority_queue<pair<ll, int>, vector<pair<ll, int>>, greater<pair<ll, int>> > que;
que.push({ 0, s });
memset(dis, 0x3f, (n + 1) << 3);
dis[s] = 0;
while (!que.empty()) {
int top = que.top().second;
que.pop();
if (vis[top]) continue;
vis[top] = 1;
if (vis[D]) break;
for (int i = head[top]; i; i = nxt[i]) {
int id = to[i]; if (vis[id]) continue;
if (dis[id] > dis[top] + cost[i]) {
dis[id] = dis[top] + cost[i];
que.push({ dis[id], to[i] });
}
}
}
}
signed main() {
//freopen("s.txt", "r", stdin);
get_prime();
begin();
read(n); read(m); read(O); read(D);
for (int i = 1; i <= m; ++i) {
read(p[i].u); read(p[i].v); read(p[i].a); read(p[i].p);
}
sort(p + 1, p + 1 + m);
int num = Binary();
init(n);
for (int i = 1; i <= m; ++i)
if (p[i].a >= num) add(p[i].u, p[i].v, p[i].p);
else break;
dij(O);
printf("%d %lld\n", num, num * dis[D]);
}