質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

918閲覧

vector<Edge>の配列とmap<int, set<Edge>>の違い

penguinshunya

総合スコア140

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2018/10/27 04:17

編集2018/10/27 04:26

AtCoder Beginner Contest 035 の D - トレジャーハント を解いているのですが、道の情報を保持するデータ構造の違いにより、通ったり通らなかったりします。

具体的には、道の情報をvector<Edge>の配列として持つとACなのですが、map<int, set<Edge>>として持つとWAになります(Edgeクラス内では、メンバ変数と<演算子の定義を行っています)。

その原因がどうしてもわからないため、質問いたしました。
vector<Edge>の配列とmap<int, set<Edge>>の違いを教えていただけると嬉しいです。

WAのソースコード
ACのソースコード

2つのソースコードのdiff

bash

1$ diff wa.cpp ac.cpp 216c16 3< map<int, set<Edge>> edge1, edge2; 4--- 5> vector<Edge> edge1[100010], edge2[100010]; 650,51c50,51 7< edge1[a].insert({a, b, c}); 8< edge2[b].insert({b, a, c}); 9--- 10> edge1[a].push_back({a, b, c}); 11> edge2[b].push_back({b, a, c});

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

自己解決

自己解決しました。

C++のsetでは、<演算子を使って重複排除が行われているようです。そして、a < bでもb < aでもない要素同士が同じ要素とみなされます(==演算子は使われないようです)。例えば、以下のコードを実行すると「1」が出力されます。

c++

1#include <bits/stdc++.h> 2 3using namespace std; 4 5class Person { 6public: 7 string name; 8 int age; 9 bool operator<(const Person &that) const { 10 return age < that.age; 11 } 12}; 13 14int main() { 15 set<Person> s; 16 s.insert({"takaya", 29}); 17 s.insert({"shunya", 29}); 18 cout << s.size() << endl; 19 return 0; 20}

Personクラスの<演算子を次のように書き換えることで、想定外の重複排除は行われなくなりました。

c++

1bool operator<(const Person &that) const { 2 if (age != that.age) { 3 return age < that.age; 4 } else { 5 return name < that.name; 6 } 7}

投稿2018/10/27 06:21

編集2018/10/27 09:37
penguinshunya

総合スコア140

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

こんにちは。

構造が全く異なりますよ。
vectorの方はpush_backで追加しているので、複数回同じインデックスへEdgeを登録するとそれらが全て登録されます。
mapの方はinsertで追加しているので、複数回同じインデックスへEdgeを登録すると最初のものだけが登録され、残りは無視されます
恐らく、eget1[index]を枚挙する処理があると思いますが、vectorは登録されたものが全て枚挙され、mapの方は最初の1つだけが枚挙されます。

mapは「既に登録済だったら更にsetへinsertする」というようなコードが必要な筈です。

投稿2018/10/27 04:30

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

penguinshunya

2018/10/27 05:02

こんにちは。回答ありがとうございます! 貼っていただいたリンクはmapのinsertですが、僕の実装のinsertはsetです。これはただのリンクの貼り間違いでしょうか?それとも回答の内容すべてが勘違いによる間違いと考えていいでしょうか?
Chironian

2018/10/27 05:06

ああ、読み違えてました。確かに、setのinsertを呼び出してますね。 となると、その後の枚挙時にでてくる順序の相違でしょうか。 vectorは登録順、setは内部的にソートしている順だったはずです。
penguinshunya

2018/10/27 05:38

列挙順以外は特に異なる点はないでしょうか?(構造の違いは置いておいて)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問