タイトル
多忙の16日後に、人類の未来は、十分なエネルギーを集めています。しかし、戦争とバイオレットの惑星で、愚かさのZの副官ので、地球applepiのリーダーはバイオレットプラネットで投獄邪悪な黒魔術師Vaniです。ネスカフェに科学技術のこの野心的なプロジェクトを再起動するには、人類がXLK、Poet_shyのエリートチームを派遣しており、3人lydrainbowcat、タイムトンネルを通って、指導者がapplepi惑星バイオレットを保存する運命。一つだけドアapplepi投獄場所は、地元の人々は「黒魔術師の門。」それを呼び出します フリービューに権利がないドアに描か図パスワードのドアを開け、各点における度数の値がゼロより大きいとサブピクチャモジュロ十億九の偶数です。ここでサブグラフ(V、E)のように定義される:エッジEのV点セットとピクチャがEはVのエンドポイント側で任意のサブセットであります しかしVaniは、このパスワードが単純すぎだと思うので、ドア上のグラフは動的です。縁なしの図は、最初だけN頂点。ドア制御システムの協働構造Vani M回、エッジが図に追加されるたびに。あなたは偉大な指導者のapplepiを節約するために、刑務所の黒魔術師を開くことができるように、各操作の後に正しいパスワードを入力する必要があります。
入力出力
最初の行は二つの整数N及びMを含有します 次のM行は、各列二つの整数AとBは、ゲーティングシステムの代わりに自由縁部(A、B)を追加します。
Mの出力ラインの合計は、各操作パスワードを示します。
サンプル入力
4 8 3 1 3 2 2 1 2 1 1 3 1 4 2 4 2 3
サンプル出力
0 0 1 3 7 7 15 31
書式#include <iostreamの> の#include <cstdioを> する#include <アルゴリズム> 書式#include <CStringの> の#include <fstreamの> の#include < 設定 > の#defineは長い長いでしょ 使用して 名前空間はstd; int型読み取り(){ int型 RES = 0、F = 1 。 char型のCH; CH = GETCHAR()。 一方、(CH < ' 0 ' || CH> ' 9 ' ){ 場合(CH == ' - ')F = - 1 。 CH = GETCHAR()。 } 一方、(CH> = ' 0 ' && CH <= ' 9 ' ){ RESの =のRES * 10 +(CH- ' 0 ' )。 CH = GETCHAR()。 } 戻り RES * F。 } のconst int型 MAXN = 200005 。 constの LL MOD = 1000000009 ; INTのN、M。 セット < 整数 > U [MAXN]。 LL ANS; int型メイン(){ N、M =; =(読み取り))(読み取ります。 以下のために(int型 i = 1 ; iは= N <; ++ I)のu [i]は.insert(I)。 以下のために(int型 I = 1 ; I <= M; ++ I){ int型のCを、B。 B = リード()。 C = リード()。 int型 FL = 0 ; 用(セット < INT > ::イテレータITER = uは[B] .begin();!ITER = U [B] .END(); ++ ITER){ int型 P = * ITER。 もし(U [C] .count(P)){ FL = 1 。 破ります; } } U [B] .insert(C); U [C] .insert(B)。 もし(FL)ANS = ANS * 2 + 1 。 printf(" %LLDする\ n " 、ANS)。 } FCLOSE(STDIN)。 FCLOSE(STDOUT)。 リターン 0 ; }
しかし、このコードの速度と精度を保証することは困難である、すべての後に、1個の環がまた再び更新を見つけることができるようになります提案を、満たすことです。絶対タイムアウト。
このように、私たちの互いに素-セットがあります。(ディスジョイントセットは私が書いていないものです)
同じコレクション内の両端場合では、同じコレクションに参加していない場合は、それ* + 1 2、、互いに素セットを使用して、答えを変更しません。
ACcode:
書式#include <iostreamの> の#include <cstdioを> する#include <アルゴリズム> 書式#include <CStringの> の#include <fstreamの> の#include < 設定 > の#defineは長い長いでしょ 使用して 名前空間はstd; int型読み取り(){ int型 RES = 0、F = 1 。 char型のCH; CH = GETCHAR()。 一方、(CH < ' 0 ' || CH> ' 9 ' ){ 場合(CH == ' - ')F = - 1 。 CH = GETCHAR()。 } 一方、(CH> = ' 0 ' && CH <= ' 9 ' ){ RESの =のRES * 10 +(CH- ' 0 ' )。 CH = GETCHAR()。 } 戻り RES * F。 } のconst int型 MAXN = 200005 。 constの LL MOD = 1000000009 ; INTのN、M。 INT [MAXN] F。 ANS LL; int型 find_f(int型X){ 戻り X == F [x]はx:F [X] = find_f(F [X])。 } int型のmain(){ N)=(読み取り; M = 読み取ります()。 以下のために(int型 i = 1 ; iは= N <; ++ I)F [I] = I。 以下のために(int型 I = 1 ; I <= M; ++ I){ int型のCを、B。 B = リード()。 C = リード()。 INT Q = find_f(B)、P = find_f(C); もし(Q =!P){ F [Q] =のC。 } 他ANS =(ANS * 2 + 1)%MOD。 printf(" %LLDする\ n " 、ANS)。 } FCLOSE(STDIN)。 FCLOSE(STDOUT)。 リターン 0 ; }
しかし、それは今、私は非常にこのアプローチの正しさを証明することはできません。私は考えることができる唯一の説明は、同じセットの場合、2は新しく追加された側と、このパスが等価である。この時点で、ユニコムポイントを終わるパスを見つけるためにバインドされていることです。この時点で、その後の円を2点のみを構成する新たに追加されたパスの側面は、それが+1である新しいサブピクチャである。新たなエッジを追加し、そのパスを代わりに使用することができるが、その結果、二重元のプログラム。これは* 2です。