限り、あなたは持っているように、ロボットの無限の数が吹いた、あなたは彼らがスプリングフィールドのやりたいことができるようになります。・Brotherton
説明[タイトル]
少し
ジェイソンの国有\(N \)都市で\(M \)は、単方向のパスを接続します。ジェイソンは、国の首都である\(N \) 。あなただけの国の首都ジェイソンが勝つことができるようになります破壊する必要があります。自分の消費を最小限にするためには、ロボットがこのタスクを達成吹い使用することを決定しました。唯一の難点は、ジェイソン国はエンチャントが都市に入ることができません破壊しない、保護する必要があり、市内の魅力の一部です。そして、各都市の区は、あなたが街を入力したい場合は、あなたがこの街の魅力を維持するために、すべてのエンチャント・ジェネレータを破壊する必要があり、他の都市で配布いくつかエンチャント・ジェネレータによって維持されています。今、あなたはロボットの無限の数は市が一度入力し、吹いている、ロボットは即座にターゲット(エンチャント・ジェネレータ、または国のジェイソン資本を)破壊、爆発させた吹いたことができ、そしてもちろんロボット自身が一緒に破壊されます。ジェイソンに国のために必要な最小限の時間を打つ:あなたが知っている必要があります。
[入力フォーマット
最初の行の2つの正の整数N、M。次のM行、各行3つの正の整数\(u_i、V_I、w_i \)は、都市から発現\(u_i \)都市に\(V_I \)一方向道路、この経路を介して吹いたロボットが必要\(w_i \)時間。後\(N \)線、それぞれが都市を記述する。最初は、正の整数である\(L_iを\) 、使用されるこのエンチャントエンチャント都市発生を維持するための代表の数。後\(L_iを\)\(1 \) 〜\(N \)各エンチャント生成器の位置を表し市ID、。場合は\(L_iを= 0 \) 、それは確実に、市は何もエンチャント保護されていないことを示します\(L_1 = 0 \) 。
[出力形式]
のみ正の整数が含まれている、国のために必要なジェイソン最小時間を破りました。
---
[コーチング]アイデア
は制限のエンチャントがない場合、この問題はもう一度それを実行しなければならないことは明らかである(ダイクストラ\)\の前に。
一見すると、この質問は、トポロジカル整列を考えました。
各点の最短算出ソース点までの最短距離の前に検査室に書き込まれ、その後、トポロジーワードシーケンスジェネレータ更新し(\をANS [I] =最大 (DIST [i]は、ANS [J]) \) 、どの都市\(J \)エンチャントジェネレータは、都市維持するために\(私は\)エンチャントを。
大規模なサンプルに一度、光栄
試験の終わりに、
\(\カラーレッド{} {間違った\回答の\ qquad10} \)
しかし、実際には、この問題は、ライン上の最短経路アルゴリズムに若干の変更のみが必要になります。
開いた3つのアレイ\(DIST、TME、ANS \)、\ (DISTは、[I]は\)ソースポイント表す\を(私は\)の最短距離であり、\は(TME [I] \)点を表します\(iは\)最初にこの時間エンチャントで放出し、\(ANS [I] \)都市ことを示す\が(iは\)最初することができた(\ [I] ANS)を\際に吹き。
明らかに、\(ANS [I] = MAX(DIST [I]、TME [I])\) 。
以下のための\(TME [I] \)、\ (Lで\ FORALL J \ [I]、TME [I] = MAX(ANS [J])\) 、\は(L [i]が\)代表は、都市を維持\(私は\)都市のコレクションエンチャント。
その後、直接再実行(ダイクストラ\)\、しかし、あなたは、更新したい\(L [i]が\)をするためには、市内のすべての後に(私は\)\ヒープに。
最終的な答えは\(ANS [N-] \) 、時間複雑度\(O(N-Mログ)\) 。
[]コードの実装
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#define re register
using namespace std;
typedef long long ll;
ll n, m;
ll head[100005], pre[150005], to[150005], val[150005], len;
ll h2[100005], p2[100005], t2[100005], l2, in[100005], ans[100005], dis[100005], tme[100005];
bool vis[100005];
ll read() {
ll ret = 0, flag = 1;
char ch = getchar();
while (ch > '9' || ch < '0') {
if (ch == '-') flag = -1;
ch = getchar();
}
while (ch <= '9' && ch >= '0') {
ret = ret * 10 + ch - '0';
ch = getchar();
}
return ret * flag;
}
void insert(ll u, ll v, ll w) {
to[++len] = v, val[len] = w, pre[len] = head[u], head[u] = len;
}
void insert2(ll u, ll v) {
t2[++l2] = v, p2[l2] = h2[u], h2[u] = l2;
}
void dijkstra() {
for (re int i = 1; i <= n; i++) dis[i] = 0x7fffffff;
dis[1] = tme[1] = ans[1] = 0;
priority_queue< pair<ll, ll> , vector< pair<ll, ll> > , greater< pair<ll, ll> > > q;
q.push(make_pair(0, 1));
while (!q.empty()) {
ll c = q.top().second;
q.pop();
if (vis[c]) continue;
vis[c] = 1;
for (re ll i = head[c]; i != 0; i = pre[i]) {
if (ans[c] + val[i] < dis[to[i]]) {
dis[to[i]] = ans[c] + val[i];
if (!in[to[i]]) {
ans[to[i]] = max(dis[to[i]], tme[to[i]]);
q.push(make_pair(ans[to[i]], to[i]));
}
}
}
for (re ll i = h2[c]; i != 0; i = p2[i]) {
if (in[t2[i]]) {
in[t2[i]]--;
tme[t2[i]] = max(tme[t2[i]], ans[c]);
if (!in[t2[i]]) {
ans[t2[i]] = max(dis[t2[i]], tme[t2[i]]);
q.push(make_pair(ans[t2[i]], t2[i]));
}
}
}
}
}
int main() {
n = read();
m = read();
ll u, v, w;
for (re int i = 1; i <= m; i++) {
u = read(), v = read(), w = read();
insert(u, v, w);
}
for (re int i = 1; i <= n; i++) {
in[i] = read();
for (re int j = 1; j <= in[i]; j++) {
u = read();
insert2(u, i);
}
}
dijkstra();
printf("%lld\n", ans[n]);
return 0;
}