説明
最近、XiaoHiがプレイするのが好きなゲームであるSimCityの新しいModがオープンしました。このModでは、プレイヤーは複数の都市を所有できます。
しかし、問題は次々と続いています-リトルハイは現在Nの都市を手にしており、これらのNの都市のいずれか2つの間に道路を建設するコストを知っています。リトルハイはそれができるだけ少なくなることを知りたがっています。任意の2つの都市は、構築された道路を介して互いに到達できます(3つの都市A、B、Cがあり、ABとBCの間に道路を構築するだけでよいと仮定すると、ACはこれらの2つの接続された道路を通過することもできます)。
ヒント:プリムのアルゴリズムがダイクストラのアルゴリズムΣ(っ°Д°;)っと非常に似ている理由はわかりません。×閉じる
ヒント:プリムのアルゴリズムがダイクストラのアルゴリズムΣ(っ°Д°;)っと非常に似ている理由がわかりません。
リトルホーもリトルハイがこのゲームをずっとプレイしているのを見ていたので、彼は自分の考えを提案しました。
リトルハイは怒って言った:「あなたはOCDが何を意味するか知っていますか?」
それでリトルホーは黙って、あえて話すことをしませんでした。
リトルハイは鼻を鳴らし、次のように述べました。「また、この機会に、最小スパニングツリーとは何かをお教えします。最初に名前の由来について話します。スパニングツリーという用語は、Gが由来する特定の画像に関連しています。つまり、ツリーTがスパニングツリーであるとは言えず、TはGのスパニングツリーであるとしか言えません。スパニングツリーの意味は、TとGのノードが同じであり、TがGのエッジセットは、いわゆるスパニングツリーであるGのエッジセットのサブセットです。最小スパニングツリーは、Gのすべてのスパニングツリーの最小エッジ重みを意味します。」
「それでは、最小全域木が複数存在する可能性がありますか?」リトルホーは尋ねました。
リトルハイはうなずいて答えました。「はい、この質問は最小スパニングツリーのエッジウェイトの合計を出力するだけで済みます。これが唯一の質問である必要があります。」
リトルホーは頭をかいて、「それならどうすればいいの?まったく手がかりがない。列挙法を使うと、時間計算量が指数関数的になるので、絶対にできない!」と言った。
「ゆっくり聞いてください!」リトル・ハイは次のように述べています。「まず、結論を証明したいと思います。都市i(i≠1)の場合、iと都市1の間の距離が他の都市j(j≠ 1)および都市1からの距離、次にエッジ(1、i)は特定の最小全域木に存在する必要があります。」
「都市1からの最短のエッジは、特定の最小全域木に属している必要がありますか?それは合理的に聞こえますが、なぜですか?」リトルホーは尋ねました。
リトル・ハイはうなずきました。「証拠はこれです。最小全域木Tの場合、(1、i)が含まれている場合、結論が証明されているので、(1、i)は状況ではないと見なします。1および私は間違いなく特定のパスで接続されます(それは森ではなく木であるため)、1-p1-p2 -...- pk-iであると仮定しましょう。 "
「うーん、じゃあなに?」
「それで、エッジ(1、p1)を削除してエッジ(1、i)を追加した場合、これはまだスパニングツリーですか?」リトルハイは尋ねました。
「ポイントは変更されておらず、エッジセットはまだグラフGのサブセットであるため、ツリーではないかどうかを確認するだけで済みます。すべてのポイントは接続されたままで、リングはありません(エッジを追加した後)。 (1、i)、リング1-p1-p2 -...- pk-i-1は1つだけですが、(1、p1)は削除されています)!つまり、これはまだツリーです。 ..この変更後も、まだツリーツリーです。」リトルホーはしばらく考えて言った。
「修正スパニングツリーをT 'と呼ぶと、(1、p1)のコストが(1、i)のコスト以上であるため、 T 'のエッジの重みはT以下であり、T自体はすでに最小全域木であるため、T'も最小全域木になることを見つけるのは難しくありません... "リトルホーは突然叫びました:"つまり、結論は次のように証明されています。(1、i)このエッジは最小全域木に存在する必要があります。」
「そうです!長征の最初のステップが完了したので、最初のステップに従うだけで済みます!」とリトルハイは言いました。
「どういう意味ですか...次の状況はもっと複雑になるでしょう?」リトルホーは戸惑いました。
リトルハイはため息をついて言いました:「愚かな...あなたはそう思う、エッジ(1、i)が特定の最小スパニングツリーに存在する必要があると確信しているなら、私はダイクストラアルゴリズムのアイデアを模倣して1を組み合わせる1つのポイントにマージすると、残りのN-2ポイントとこのポイントの最小スパニングツリーを見つけることが問題になりますか?問題は変わっていませんが、スケールが縮小されているため、これを行う必要があるのは1回だけです。 、この問題は完全に解決されていませんか?」
リトルホーはそれについて考え、次のように述べました。「つまり、Nポイントの最小全域木問題の場合、ポイント1に最も近いポイントiを見つけて、これら2つのポイントをマージし、N-1ポイントを残します。新しいポイント1に最も近いポイントi 'を見つけ、これら2つのポイントをマージし、N-2ポイントを残します...など、最後のポイントが残るまで、前のすべてのポイントをマージします。サイドのコストを合計します。それが答えです!」
「ラスはあなたに教えて、急いでプログラムを書くことができます!後でそれを使います!」
閉じる
入る
各テストポイント(入力ファイル)には、テストデータのセットが1つだけあります。
テストデータのセット:
最初の行は整数Nで、Hiが所有する都市の数を表します。
次のN行はN * N行列Aで、任意の2つの都市間の道路建設のコストを表します。i番目の行のj番目の数字はAijで、i番目の都市とj番目の都市を表します。間の道路を建設するコスト。
100%のデータの場合、N <= 10 ^ 3が満たされ、任意のiの場合、Aii = 0であり、任意のiの場合、jはAij = Aji、0&ltAij&lt10 ^ 4です。
出力
テストデータの各セットについて、整数Ansが出力されます。これは、任意の2つの都市が建設された道路を介して互いに到達するために必要な最小建設コストを表します。
サンプル入力
5 0 1005 6963 392 1182 1005 0 1599 4213 1451 6963 1599 0 9780 2789 392 4213 9780 0 5236 1182 1451 2789 5236 0
サンプル出力
4178
アイデア:プリムアルゴリズム
(質問からプリムアルゴリズムを使用するポイントを学ぶことができる理由がわかりません(質問を除く):https://blog.csdn.net/with_wine/article/details/113823749)
実装コード:
#include<stdio.h>
#include<string.h>
int a[1010][1010],dis[1010],book[1010];
int n,u,min,sum,inf=99999999;/*这个无穷大inf*/
int main()
{
int i,j;
while(~scanf("%d",&n))
{
sum=0;/*我们最后输出的结果*/
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
scanf("%d",&a[i][j]);
}
}
for(i=1;i<=n;i++)
{
book[i]=0;
dis[i]=a[1][i];
}
/*修改信息*/
book[1]=1;
dis[1]=0;
for(i=1;i<n;i++)
{
min=inf;
for(j=1;j<=n;j++)
{
if(book[j]==0&&min>dis[j])
{
min=dis[j];
u=j;
}
}
/*从标号为1的点出发,找到距离它最近的点,标记*/
book[u]=1;
sum+=dis[u];
for(j=1;j<=n;j++)
{
if(book[j]==0&&dis[j]>a[u][j])
dis[j]=a[u][j];
}
}
printf("%d\n",sum);
}
}
印象を深めるために、別のプリムアルゴリズムアプリケーションの問題を 考えてみましょう:https://blog.csdn.net/with_wine/article/details/113722148(〜 ̄▽ ̄)〜どういたしまして
高度な記事:https://blog.csdn.net/with_wine/article/details/113980197