そのため、さまざまなグラフで多くの DFS を実行するというプログラミング コンテストの問題がありました。
最初に、グラフ (隣接リスト表現) をセットのベクトルとして表現しました。
vector< set<int> > graph;
また、空のセットを使用するたびに、指定されたノード数に従ってグラフを初期化するには:
set<int> tmpSet;
そして、私はそれを次のように初期化しました:
for(int j=0;j<N;j++)//N was the number of nodes needed for the graph
graph.push_back(tmpSet);
そして私は使った
graph.clear();
毎回グラフを空にします。
後でエッジを挿入するには、std::set の挿入機能を使用しました。
//Insert directed edge from u to v
graph[u].insert(v);
graph[v].insert(u);
その結果、プログラムは大量のメモリを消費し、遅すぎてテストに合格できませんでした。一定時間の操作である push_back 関数を使用して std::list でも同じことが起こりました。次に、std::vector に変更すると、メモリ消費量が最小限になり、3 秒でテストに合格しましたが、std::set と std::list は 20 秒でもテストに合格できませんでした。
私の疑問は、それが内部セットとリストのスペースを解放することと関係があるということですが、なぜベクトルの動作が異なるのでしょうか?
だから私の質問は、なぜこれが起こったのかを誰かが説明できるかどうかです。そうすれば、別のコンテナ内にコンテナがあるような状況で stl コンテナがどのように動作するかをよりよく理解できます。
編集: いくつかの追加情報: ノードの数は約 N=3000 で、テストの数は 1000 を超えていました。つまり、1000 を超えるグラフをすべて変数「グラフ」に保持する必要がありました。また、set は O(lgn) 時間で挿入され、ベクトルとリストは O(1) にあることを認識しているため、set がvector よりも少しだけ長くかかる理由を理解しています。しかし、なぜ std::list も失敗したのでしょうか? また、set と list は 100Mb のメモリ使用量で終了し、vector は 3Mb で終了したことにも触れておきます。
最後の編集では、グラフ (リスト バージョン) をどのように使用しているかを正確に示すコードを次に示します。プログラムの他の場所では、メモリの解放やグラフ データの変更は行われません。
vector< list<int> > graph;
list<int> tmpList;
int T; //num of test cases
int N; //num of nodes
int M; //num of edges
int main ()
{
int u,v;
scanf("%d",&T);//Read test cases
for(int i=0;i<T;i++){
scanf("%d %d",&N,&M);//Read number of nodes and number of edges
for(int j=0;j<N;j++)
graph.push_back(tmpList);
for(int j=0;j<M;j++){
scanf("%d %d",&u,&v);//Read edge from u to v
graph[u].push_back(v);
graph[v].push_back(u);
}
dfs();
graph.clear();
}
}