結果
| 問題 |
No.2387 Yokan Factory
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2023-07-21 22:10:27 |
| 言語 | D (dmd 2.109.1) |
| 結果 |
AC
|
| 実行時間 | 756 ms / 5,000 ms |
| コード長 | 2,200 bytes |
| コンパイル時間 | 3,450 ms |
| コンパイル使用メモリ | 187,136 KB |
| 実行使用メモリ | 25,868 KB |
| 最終ジャッジ日時 | 2024-09-21 23:41:17 |
| 合計ジャッジ時間 | 10,225 ms |
|
ジャッジサーバーID (参考情報) |
judge2 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 35 |
ソースコード
import std;
struct node {
int vertex;
int weight;
int width;
}
void main () {
int N, M;
long X;
readln.read(N, M, X);
node[][] graph = new node[][](N, 0);
foreach (i; 0..M) {
int u, v, a, b; readln.read(u, v, a, b);
u--, v--;
graph[u] ~= node(v, a, b);
graph[v] ~= node(u, a, b);
}
solve(N, M, X, graph);
}
void solve (int N, int M, long X, node[][] graph) {
// 羊羹の大きさで二分探索する
// 判定問題はダイクストラ法を解くことと等価であり、ヒープキューを使ってO(|E|log|V|)らしい(しらん)
// まず、最小羊羹で到達できるかをチェック
if (!dijkstra(graph, X, 1)) {
writeln(-1);
return;
}
// 二分探索 条件: f(ok) = true かつ f(ng) = false
int ok = 1, ng = 100_000_000_1;
while (1 < abs(ok-ng)) {
int mid = (ok+ng) / 2;
if (dijkstra(graph, X, mid)) {
ok = mid;
} else {
ng = mid;
}
}
writeln(ok);
}
bool dijkstra (node[][] graph, long X, int wid) {
struct toNode {
int vertex;
long totalCost;
}
long[] comfirmedCost = new long[](graph.length);
comfirmedCost[] = long.max;
BinaryHeap!(Array!toNode, "a.totalCost > b.totalCost") PQ;
PQ.insert(toNode(0, 0));
comfirmedCost[0] = 0;
while (!PQ.empty) {
auto shortest = PQ.front; PQ.removeFront;
if (comfirmedCost[shortest.vertex] < shortest.totalCost) {
continue;
}
foreach (to; graph[shortest.vertex]) {
if (to.width < wid) {
continue;
}
if (to.weight + shortest.totalCost < comfirmedCost[to.vertex]) {
comfirmedCost[to.vertex] = to.weight + shortest.totalCost;
PQ.insert(toNode(to.vertex, comfirmedCost[to.vertex]));
}
}
}
if (comfirmedCost[$-1] == long.max || X < comfirmedCost[$-1]) {
return false;
}
return true;
}
void read(T...)(string S, ref T args) {
auto buf = S.split;
foreach (i, ref arg; args) {
arg = buf[i].to!(typeof(arg));
}
}