🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C++

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

Q&A

解決済

1回答

1077閲覧

木に対していもす法を使う問題

l_h_l_h

総合スコア22

C++

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

0グッド

0クリップ

投稿2019/09/15 15:20

この問題についてです

解法としては、木に対していもす法を使うだけなのですが、解説(の注釈)にある
「a[i]がb[i]の親であるとは限らず、再帰関数を用いる必要がある」
という部分が理解できません

私は初め、以下のようなコードを提出しました

using namespace std; typedef long long ll; const ll INF = 1e9; const ll mod = 1e9+7; typedef pair<int,int> P; #define rep(i,N) for(int i=0;i<N;i++) #define rep2(i,m,N) for(int i=m;i<N;i++) #define mm(n,m) memset(n,m,sizeof(n)) int main(){ ll n,q; cin>>n>>q; ll a[n],b[n]; ll p[q],x[q]; mm(a,0); mm(b,0); mm(p,0); mm(x,0); vector<ll>tr[n]; rep(i,n-1){ cin>>a[i]>>b[i]; tr[a[i]].push_back(b[i]); } ll ans[n+1]; mm(ans,0); rep(i,q){ cin>>p[i]>>x[i]; ans[p[i]]+=x[i]; } for(int i=1;i<n;i++){ int d = tr[i].size(); for(int j=0;j<d;j++){ ans[tr[i][j]] += ans[i]; } } for(int i=1;i<=n;i++)cout<<ans[i]<<" "; cout<<endl; } コード

vectorで親のindexに子をプッシュしていき、伝播させていく感じです
しかしこの方法では正解できませんでした
最終的に、伝播させていく部分のループを再帰を用いた深さ優先探索に書き換え、vectorで子から親への辺を張るコード(tr[b[i]].push_back(a[i]);)を追加することで正解することができました
しかし、私の頭では、a[i]<b[i]なのだから、元のコードで良いのではないか、また、子から親へも辺を張る必要があるのか(それをしないといけないケースがどのようなものか)、イマイチ分かりません

どなたか分かる方いらっしゃいましたらアドバイスお願いします

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

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

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

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

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

guest

回答1

0

ベストアンサー

AtCoder Beginner Contest 138 D - Ki のテストケースがコンテスト後に増えている件について (修正版)を参照ください。
標準入力の木のつながりを表す行a[i] b[i]において、a[i]のほうがルートに近いという前提はない(持ってはいけない)、つまり番号の小さい方が大きい方の子供になりうる、ということのようです。

投稿2019/09/15 23:28

can110

総合スコア38341

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問