学校のネットワーク(poj1236 Tarjan)

学校のネットワーク
時間制限: 1000ミリ秒   メモリ制限: 10000K
合計提出: 27846   受け入れ: 10960

説明

学校の数は、コンピュータネットワークに接続されています。協定は、これらの学校の中で開発されている:各学校は、それがソフトウェア(「受信校」)を配布先の学校のリストを保持します。Bは、学校Aの配布リストにある場合は、Aは、必ずしも学校のBのリストに表示されないことに注意してください
あなたは、契約(サブタスクA)に応じて、ネットワーク内のすべての学校に到達するためにソフトウェアのために、新しいソフトウェアのコピーを受信しなければならない学校の最小数を計算するプログラムを書くことです。さらにタスクとして、我々は、任意の学校に新しいソフトウェアのコピーを送信することにより、このソフトウェアは、ネットワーク内のすべての学校に到達することを確実にしたいです。この目標を達成するために、我々は新しいメンバーによって受信機のリストを拡張する必要があります。我々は、新しいソフトウェアを送信するどんな学校それは、それは他のすべての学校(サブタスクB)に到達しますので、行わなければならない拡張子の最小数を計算します。一つの拡張は、1校の受信機のリストに1新しいメンバーを導入することを意味します。

入力

ネットワーク内の学校の数(= 100 2 <= N <):最初の行は、整数Nを含んでいます。学校は、最初のNは正の整数によって識別されます。次のNラインの各々は、受信者のリストを示します。ラインI + 1は、学校、iの受信機の識別子が含まれています。0アン空のリストと各リストの端はラインでのみ0が含まれています。

出力

あなたのプログラムは、標準出力に2行を記述する必要があります。最初の行は一つの正の整数を含むべきである:サブタスクAの溶液を、2行目は、サブタスクBの溶液を含むべきです

サンプル入力

5 
2 4 3 0 
5 0 
0 
0 
1 0

サンプル出力

1 
2

ソース

問題解決のアイデア:タイトルは、選挙がポイントの最小値を求めていることを意味しますが、他のすべてのポイントに到達することができます任意の時点へのすべてのポイントに到達することができます
0ポイントが最大を発見することであるように入場点を求めるTarjan収縮は0点の数との程度と発音(ポイント0,0リードに接続されたすべての点の第二の程度であります数0時00分)
1の#include <iostreamの>
 2の#include <CStringの>
 3の#include <cstdioを>
 4の#include <アルゴリズム>
 5  使用して 名前空間をSTD。
6  
7  CONST  INT MAXN = 110 8  INT N。
9  INT CNT、ヘッド[MAXN]。
10  INT DFN [MAXN]、低[MAXN]、SCC [MAXN]、STK [MAXN]、インデックス= 0、sccnum = 0、トップ= 0 11  構造体のエッジ{
 12      int型V、NXT。
13 } G [MAXN * MAXN]。
14 ボイドのinit(){CNT = 0memsetの(頭、 - 1はsizeof (ヘッド))。}
 15  空隙追加(INT U、INT V){
 16      G [CNT] .V = V。
17      G [CNT] .nxt = 頭部[U]。
18      頭[U] = CNT ++ 19  }
 20  
21  空隙 tarjan(INTルート){    // tarjan模板
22      であれば(DFN [ルート])のリターン;
23      DFN [ルート] =低[ルート] = ++ 指数;
24      STK [++トップ] = 根。
25  
26      のためにINT iはヘッド[ルート] =;〜iは、iが= G [i]が.nxt){
 27          のint V = G [I] .V。
28          であれば(!DFN [V]){
 29              tarjan(V)。
30              低[ルート] = 分(低[ルート]、低い[V])。
31          }
 32          そう であれば(SCC [V]!){    // 如果还在站内
33              低[ルート] = 分(低[ルート]、DFN [V])。
34          }
 35      }
 36      であれば(低[ルート] == DFN [ルート]){
 37          sccnum ++ 38          のための(;;){
 39              、INT X = STK [top-- ]。
40              SCC [X] = sccnum。
41              であれば(X ==ルート)ブレーク42          }
 43      }
 44  }
 45  
46  INT  における [MAXN]、アウト[MAXN]。
47  ボイド解く(){
 48      、インデックス= 0、sccnum = 0、トップ= 0 49      のmemset(DFN、0はsizeof (DFN))。
50      のmemset(低、0はsizeof (低))。
51      のmemset(SCC、0はsizeof (SCC))。
52      のmemset(STK、0はsizeof (STK))。
53      のためにINT iは= 1 ; iが<= N; I ++ ){
 54          であれば(!DFN [I]){
 55              tarjan(I)。
56          }
 57      }
 58      であれば(sccnum == 1){    // 特判
59          のprintf(" 1 \ N0 \ n " );
60          リターン;
61      }
 62      のためにINT iは= 1 ; iが<= sccnum; I ++ ){
 63          における [I] = 0アウト [I] = 0 ;
64      }
 65      のためにINT iは= 1 ; iが<= N; I ++){    // 重新建图
66          のためにINT J =頭部[I];〜J; J = G [J] .nxt){
 67              のint V = G [J] .V。
68              であれば(SCC [I] =!SCC [V]){
 69                   [SCC [V]] ++ ;
70                  アウト[SCC [I]] ++ ;
71              }
 72          }
 73      }
 74      INT RES1 = 0、RES2 = 0 75      のためにINT iが= 1 ; iが<= sccnum; I ++ ){
 76          であれば [I] == 0)RES1 ++ 77          であればアウト [I] == 0 RES2 ++) 78      }
 79      のprintf(" %D \ N%D \ n " 、RES1、MAX(RES1、RES2))。
80  }
 81 
82  INT メイン(){
 83      ながら(scanf関数(" %のD "、&​​N)== 1 ){
 84          のinit();
85          のためにINT iは= 1、D1と、iが<= N; I ++ ){
 86              ながら(scanf関数(" %のD "、&​​D1)== 1 && D1){
 87                  追加(I、D1)。
88              }
 89          }
 90          (解きます)。
91      }
 92      リターン 0 93  
94 }
コードの表示

 

おすすめ

転載: www.cnblogs.com/qq-1585047819/p/11962467.html