ドラゴンボール
猿王(悟空)が一緒にドラゴンボールのすべてを収集することは非常に困難ですので、五百年後、ドラゴンボールの数は、予想外に増加します。
彼の国では、N個の都市を持っており、世界でもNドラゴンボールが正確にあります。i番目の都市ではまず、i番目のドラゴンボールのため、神聖なドラゴンは意志プットそれを。長い年月を経て、いくつかの都市のドラゴンボール(S)は、他の都市に輸送されるだろう。ドラゴンボールを収集するためにフライングニンバス雲、魔法の飛行雲を取るために体力悟空のプランを保存するには。
悟空が1つのドラゴンボールの情報を収集するたびに、彼はあなたにそのボールの情報を聞いてきます。あなたはボールが配置されている都市を彼に伝える必要がありますし、どのように多くのドラゴンボールがその都市であり、あなたもボールがこれまでに搬送された回数を彼に伝える必要があります。
入力
入力の最初の行は、単一の正の整数T(0 <T <= 100)です。
N及びQ(2 <N <= 10000、2 <Q <= 10000):それぞれの場合について、最初の行は、2つの整数を含んでいます。
以下のQラインの各々は以下のフォーマットとして事実や質問のいずれかを含む:
TABを:Aと同じ都市にあるすべてのドラゴンボールがでB番目ボール都市に輸送されている次の2つの都市と仮定することができます。異なっています。
QA:悟空はX(ボールアト市のidがである)、Y(X番目の都市でボールのカウント)とZ(ATHボールのtranporting時間を)知ってほしいです。(1 <= A、B <= N)
N及びQ(2 <N <= 10000、2 <Q <= 10000):それぞれの場合について、最初の行は、2つの整数を含んでいます。
以下のQラインの各々は以下のフォーマットとして事実や質問のいずれかを含む:
TABを:Aと同じ都市にあるすべてのドラゴンボールがでB番目ボール都市に輸送されている次の2つの都市と仮定することができます。異なっています。
QA:悟空はX(ボールアト市のidがである)、Y(X番目の都市でボールのカウント)とZ(ATHボールのtranporting時間を)知ってほしいです。(1 <= A、B <= N)
出力
各テストケースのために、出力は、テストケースの数は、サンプル出力としてフォーマットさ。次に各クエリ、出力のための3つの整数値を持つ行が空白でsaparated XYZ。
サンプル入力
2
3 3
T 1 2
T 3 2
Q 2
3 4
T 1 2
Q 1
T 1 3
Q 1
サンプル出力
ケース1:
2 3 0
ケース2:
2 2 1 3 3 2
質問の意味:Nパール、私の街のIパール与えられました。T:X、Y。どこのコレクションは、x yの上に置かれます。Q:X。ここで、xは、クエリの集合である:Xコレクション、要素の総数は、Xコレクション; xは動きの数です。
パース:コレクションが直接そのルートを見つけるために、X。コレクション内の要素の数Xここで、直接すべての[]配列には、合併の時に維持されます。
移動され、X回数をカウントすることがいかに重要です。試料2は、13に接続され、ツリー上で、1 2、1 2 3.1懸念されており、実際に接続2 3、ティム[2] ++が、ティム[1]が変更されていません。ティム[X] + =ティム[PR [X]:したがって、ティムを加算する値は、更新中()を見つけます。モバイルノードの数は、携帯電話番号+ルートノード自身です。その祖先は、将来の世代に転送回数を増やすために、バックアップします。コードはまだ、意味の少しを扱っている(参加される)ティム[FA]最初++に及び、FAティム[]の子孫は、更新に次の操作を残しました。
#include <iostreamの> する#include <cstdioを> する#include <CStringの> する#include <アルゴリズム> の#include < セット > 使用して 名前空間STDを、 const int型 MAXN = 2E4 + 10 。 INT PR [MAXN]、すべて[MAXN]、ティム[MAXN]。 整数N、M。 ボイドのinit() { ために(INTは iは= 1 ; I <= N; I ++ ) { PR [I] = I。 すべて[I] = 1 。 ティム[I] = 0 ; } } int型の検索(INT X) { 場合(X == PR [X]) リターンX。 INT FA = PR [X]。 PR [X] = 見つける(PR [X])。 ティム[X] + = ティム[FA]。 戻りPR [X]。 } ボイド(参加int型、int型B)を { INT FA =()、FBを見つける= (B)を見つけます。 もし(!FA = FB) { PR [FA] = FB。 すべて[FB] + = すべて[FA]。 ティム[FA]++; } を返します。 } int型のmain() { int型、T。 int型 AC = 1 ; scanf関数(" %のD "、&T)。 一方、(t-- ) { のprintf(" ケース%のD:\ n "、AC ++ )。 scanf関数(" %D%D "、&N、&M)。 初期化(); チャー CH [ 5 ]。 一方、(M-- ) { // のscanf( "%のC"、&CH); scanf関数(" %S " 、CH)。 INT X、Y。 もし(CH [ 0 ] == ' T ' ) { scanf関数(" %D%D "、およびX&Y)。 (x、y)を参加します。 } 他 { scanf関数(" %のD "、&x)は、 int型の半ば= (x)を見つけます。 coutの <<半ば<< " " <<全て[中期] << <<ティム[X] << ENDL。 } } } }