質問
AtcoderBeginnerContest137-Eにおいて、WAやTLEが生じる原因がわからない。
(動作チェック用の出力をコメントアウトしてあります。)
問題文
1 から N までの番号がつけられた N 頂点と M 辺からなる有向グラフがあります。
i 番目の辺は頂点 A_i から頂点 B_i へと向かい、この辺の上には C_i 枚のコインが置かれています。
また、頂点 N にはボタンが設置されています。
このグラフ上でゲームを行います。 あなたは頂点 1 でコインを 0 枚持ってゲームを開始し、辺をたどってコインを拾いながら頂点 N を目指します。
1本の辺を通るには 1 分の時間がかかり、辺を通るたびにその辺の上に置かれているすべてのコインを拾うことができます。
ゲームの世界ではよくあるように、ある辺を通ってその上のコインを拾っても、その辺を次に通る際には同じ枚数のコインが再び出現しており、それらを再び拾うことができます。
頂点 N に到着したとき、ボタンを押してゲームを終了することができます。(ボタンを押さずに移動を続けることもできます。)
ただし、ゲームを終了する際に、ゲーム開始からの経過時間を T 分として T×P 枚のコインの支払いが要求されます。
持っているコインの枚数が T×P 枚未満の場合は、代わりに持っているコインをすべて支払います。
この支払いの後に残ったコインの枚数があなたのスコアとなります。 獲得できるスコアの最大値が存在するか判定し、存在する場合はその最大値を求めてください。
方針
- かかった時間に応じて最後に支払う -> 負の所持コインを許容し、辺を通るたびに支払う。
- 1(スタート)からN(ゴール)にたどり着けなくなる辺は除去。
- ベルマンフォード法を使用して最大を調べる。また、無限にコインを獲得するルートを検出。
結果
ほとんどはAC(正解)。一部WA(不正解)とTLEが生じる。
ソースコード
cpp
1#include <iostream> 2#include <vector> 3#include <queue> 4using namespace std; 5 6#define INF 100000 7 8int N, M, P; 9 10typedef struct edge 11{ 12 int from; 13 int to; 14 int cost; 15} edge; 16 17int main() 18{ 19 cin >> N >> M >> P; 20 int dist[N + 1];//頂点ごとのコストを格納 21 vector<edge> e1;//不要部分除去前の辺リスト 22 vector<edge> e2;//不要部分除去後の辺リスト 23 //コストの初期化 24 for (int i = 1; i <= N; i++) 25 { 26 if (i != 1) 27 dist[i] = INF; 28 else 29 dist[i] = 0; 30 } 31 //辺の登録 32 { 33 edge ed; 34 for (int i = 0; i < M; i++) 35 { 36 cin >> ed.from >> ed.to >> ed.cost; 37 ed.cost = P - ed.cost; 38 e1.push_back(ed); 39 } 40 } 41 //Nにたどり着けなくなる頂点、辺の除去 42 { 43 int fromOne[N + 1];//1からiにたどり着ける場合fromOne[i]=1 other 0 44 int toN[N + 1];//iからNにたどり着ける場合toN[i]=1 other 0 45 for (int i = 1; i <= N; i++) 46 { 47 fromOne[i] = 0; 48 toN[i] = 0; 49 } 50 queue<int> que; 51 que.push(1); 52 while (!que.empty()) 53 { 54 fromOne[que.front()] = 1; 55 for (auto &&i : e1) 56 { 57 //cout << que.front() << "から移動" << endl; 58 if (i.from == que.front() && fromOne[i.to] == 0) 59 { 60 //cout << i.from << "->" << i.to << "へ移動" << endl; 61 que.push(i.to); 62 } 63 } 64 que.pop(); 65 } 66 //cout << "-------" << endl; 67 que.push(N); 68 while (!que.empty()) 69 { 70 toN[que.front()] = 1; 71 for (auto &&i : e1) 72 { 73 //cout << que.front() << "から移動" << endl; 74 if (i.to == que.front() && toN[i.from] == 0) 75 { 76 //cout << i.to << "->" << i.from << "へ移動" << endl; 77 que.push(i.from); 78 } 79 } 80 que.pop(); 81 } 82 for (auto &&i : e1) 83 { 84 if (fromOne[i.from] * toN[i.to] == 1) 85 { 86 e2.push_back(i); 87 } 88 } 89 } 90 //コストの緩和 91 for (int i = 0; i < N; i++) 92 { 93 for (auto &&j : e2) 94 { 95 dist[j.to] = min(dist[j.to], dist[j.from] + j.cost); 96 } 97 } 98 //負経路の探索 99 for (auto &&i : e2) 100 { 101 if (dist[i.to] > dist[i.from] + i.cost) 102 { 103 cout << "-1" << endl; 104 return 0; 105 } 106 } 107 cout << max(-1 * dist[N], 0) << endl; 108 return 0; 109} 110
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。