リレーレースリレー牛(高速電力最短経路マトリックス)

カジュアルワーキング:

  NのFJ(2 <= N <= 1,000,000) 日常の運動プログラムを実行するための中継器として選ば牛。中継場所は既存の天然T(2 <= T <=実行するように 100) 牧草地に滑走路に。(1 <= I1_i <=いくつかの農場滑走路の交差点に、各滑走路は、二つの異なる交差点I1_iとI2_iに接続され 、1 <= I2_i <=千千)。各交差点には、少なくとも2本の滑走路の終点です。牛は、各滑走路長length_i(1 <= length_i <=知っている 1000)、 及び各滑走路の数の交点を接続し、どの2つの接合部は、二つの異なる滑走路によって直接接続されていません。あなたはミーティングポイントと滑走路の景色を構成するこれらを考えることができます。リレーレースを完了するためには、すべての起動実行する前に、すべてのNの牛が1つの交差点に立つ(おそらくいくつかのミーティングポイントだけでなく、牛の上に立って)。もちろん、そのステーションは、彼らが順番にバトンを渡すことができることを確実にするために、そして最終的に設定された目的地で停止するようにスティック牛を保持します。あなたの仕事は、リレーレース開始点(S)と端部(E)を決定した場合に算出プログラム書くことである可能な限り最小の総経路長を実行している牛明らかに、このパスでなければなりませんちょうどNの滑走路の後

ソリューション:

  このような大規模な、最後見見てショックを受けN N事実、経路長迅速基本的に電力の行列です。しかし、ノードのサイズは、1〜1000であり、明らかに耐えるが、そのエッジ100、しかし、それは、離散(又は最初の建物側に実装されてもよい101(通信)までを指すのに有用であり、添え字番号再度DFSすなわち利用可能)。指標として経路長、行列の各辺の長さを迅速値行列として直接電力であろう。

  なぜべき行列の値として直接各辺の長さは?で縮小しないのですか?我々が100,000ポイントは確かに受け入れられない、ポイントを縮小する場合。また、実際に、それは経路長nを介して最短経路を求める場合は、我々は行列を定義するY、ZしなければならないパスにノードXから最小となり、その値は、各ノードの経路長であるので、無ポイントを縮小。

  しかし、それはほんの数種の後にポイントへのパスを決定し、通常の高速電力行列、であれば、我々の期待を満たすことができない、我々はについての質問の行列乗算の意味を変更することができ、次のようになります。

sum.a [I] [J] =分(sum.a [I]、[J]、aa.a [I] [K] + bb.a [K] [J])。

  オーバー配布するようなマトリックス乗算Σの分に取るように見ることができるので、我々は我々が必要なものとなっ乗算行列の形態にすることができます。

コード:

1の#include <cstdioを>
 2の#include <CStringの>
 3の#include <アルゴリズム>
 4  の#define $ 111
 5  使用して 名前空間STD。
6  int型 M、N、T、開始、行わ [$]、STA [$ * 2 ]、アウトアップ[$]、W [$]。
7インラインINT分(int型のx、int型の Y){     戻り X <Yを?X:Y。}
 8  構造体ツリー{
 9      INT [$] [$]。
10      ツリー(){memsetの(、63はsizeof(A))。}
 11      フレンドツリー演算子 * (ツリーAA、ツリーBB){
 12          ツリー和= ツリー()。
13          のために(登録INT K = 1 ; K <= M; ++ K)
 14              のため(登録INT i = 1 ; I <= M; ++ I)
 15                  のため(登録INT J = 1 ; jは<= M。 ++ j)は
 16                      sum.a [I] [J] =分(sum.a [I]、[J]、aa.a [I] [K] + bb.a [K] [J])。
17          リターン合計。
18      }
 19     友人ツリー演算子 ^(ツリーAA、INT X){
 20          ツリー和= ツリー()。
21          のために(登録をint = I 1、I <= M; ++ I)sum.aを[I] [I] = 0 ;
22          のために(; X; X >> = 1、AA = AAの*のAA)であれば(X&1)合計=合計* AA。
23          リターン合計。
24      }
 25  }。
26は、 メイン(){署名された
 27      ツリーANS = ツリーを();
28      のscanf(" %D%D%D%D "、&​​N、&T、&スタート、&)に行わ;
29      のために(登録INT i = 1 ; I <= T; ++ I)
 30          のscanf(" %D%D%D "、&​​W [i]は、& [I]、&アウト [i])と、STAの[ ++アップ] =  = [++アップ] [i]は、STA アウト[I]。
31      STA [++アップ】STA = [++ UP]、START = 行います。
32      ソート(STA + 1、STA +アップ+ 1 )。
33      、M =ユニーク(STA + 1、STA +アップ+ 1)-sta- 1 34      のために(登録INT I = 1; I <= T; ++ I){
 35          における [I] = LOWER_BOUND(STA + 1、STA + M + 1 [I]) - STA。
36          アウト [I] = LOWER_BOUND(STA + 1、STA + M + 1アウト [I]) - STA。
37          ans.a [ における [I] [ アウト [I] = ans.a [ アウト [I] [ における [I] = W [i]は、
38      }
 39      START = LOWER_BOUND(STA + 1、STA + M + 1、スタート) - STA。
40      完了= LOWER_BOUND(STA + 1、STA + M +図1に示すように、)行わ- STA。
41      のANS =のANS ^ N。
42      のprintf(" %d個の\ n " 、ans.a [開始] [完了])。
43 }
コードの表示

 

おすすめ

転載: www.cnblogs.com/OI-zzyy/p/11202571.html