ジョンが有するn個のブロックは、牧草通行複数の接続されたN、1〜数、草原。ベッシーは、牛の牧草地は、彼女が味わうなど、多くの牧草に到達したかった、おいしい目利きです。
ベッシーは常に1番から始まる牧草地、そして最終的に戻って第1牧場へ。彼女は、できるだけ多くの牧草地を通過したかった、ベッシーは、牧草地で草を通じて一度何度牧草を食べます。
牧草地は、ベッシーは大きな不便をもたらしたテイスティング仕事を与える一方向接続であるため、ベッシーは密かに散歩を逆にしたいのですが、唯一の逆行ものを持つことができます。私は草の牧草を食べにベッシー番号を尋ねました。
入力:
最初のライン:牧草数n、道路の数m。
m行は、各列は、x xとy yの一方向エッジがパスを重複しない示します。
出力:
数は、逆行性には、いくつかの牧草地まで行くことができます。
入力#1
10 7 1 2 3 1 2 5 2 4 。3. 7 。3. 5 。3。6 。6. 5 。7 2 。4. 7
出力#1
6
;長い時間ので、正式なタイトルは、表面を上に移動しますない
強連結成分を求める明確な必要性のtarjanを、
私はここでしかなりますが、質問を見て、
反対側、おなじみのビット、ええと、ああを許す、ということである
我々が縮小する必要があります前方最長の道を求めている点、ダイクストラは、最も長い道を模索逆
裏側を列挙し、
DIS1 [X-] + DIS2 [V] -sumは、[1] [所属];
しかし、我々は、保証を戻りたいです
書式#include <cstdioを> する#include <CStringの> の#include <キュー> の#include <スタック> の#include <アルゴリズム> 使用して 名前空間はstdを、 const int型 MAXN = 1E5 + 10 。 INTのN、M、予め[MAXN]、最後[MAXN]、他の[MAXN]、L。 INT PRE0 [MAXN]、last0 [MAXN]、other0 [MAXN]、L0。 ボイド ADD0(int型のx、int型のY) { L0 ++ 。 PRE0 [L0] = last0 [X]。 last0 [X] = L0。 other0 [L0] = Y。 } int型DFN [MAXN]、低[MAXN]、CNT。 ボイド追加(int型のx、int型のY) { L ++ 。 プレ[L] = 最後[X]。 最後[X] = L。 他の[L] = Y。 } INT PRE2 [MAXN]、last2 [MAXN]、other2 [MAXN]、L2。 ボイド ADD2(int型のx、int型のY) { L2 ++ 。 PRE2 [L2] = last2 [X]。 last2 [X] = L2。 other2 [L2] = Y。 } スタック < int型> S; int型はQW、[MAXN]属しています。 ボイド DFS(INT X) { [X] DFN =低[X] = ++ CNT。 s.push(X)。 用(INT P =最後[X]; P; P = 事前[P]) { int型 V = 他の[P]。 もし(!DFN [V]) { DFS(V)。 低[X] = 分(低[x]は、低[V])。 } そう であれば(!属する[V]) { 低い[X] = 分(低[x]は、DFN [V])。 } } もし(DFN [X] == 低[X]) { 属する[X] = ++ QW。 // のprintf( "%dの"、QW)。 一方、(1 ) { int型、Y = )(s.top。 s.pop(); [Y]を属し = QW。 もし(x == y)のブレーク。 } } } int型の和[MAXN]。 int型ANS; int型VIS [MAXN]。 int型DIS1 [MAXN]、[MAXN] DIS2。 PRIORITY_QUEUE <ペア< int型、int型 >> Q; ボイドダイクストラ(INT X) { memsetの(VIS、0、はsizeof (VIS))。 DIS1 [X] = 和[X]。 q.push(make_pair(DIS1 [X]、X)); 一方、(!q.empty()) { int型、U = q.top()は、第2。 q.pop(); // printfの( "%d個の\ nを!"、U); // printfの( "%d個の\ nの?"、最後の[U]); // もし(VIS [U])続けます。 // VIS [U] = 1。 用(INT P = last0 [U]; P; P =のPRE0 [P]) { int型 V = other0 [P]。 // printfの( "!!"); もし(DIS1 [V] <DIS1 [U] + 和[V]) { DIS1 [V] = DIS1 [U] + 和[V]。 q.push(make_pair(DIS1 [V]、V))。 // のprintf( "%d個の\ n"、DIS1 [V])。 } } } } ボイド dijkstra2(INT X) { memsetの(VIS、0、はsizeof (VIS))。 DIS2 [X] = 和[X]。 q.push(make_pair(DIS2 [X]、X)); 一方、(!q.empty()) { int型、U = q.top()は、第2。 q.pop(); // もし(VIS [U])続けます。 // VIS [U] = 1。 用(INT P = last2 [U]; P; P =のPRE2 [P]) { int型 V = other2 [P]。 もし(DIS2 [V] <DIS2 [U] + 和[V]) { DIS2 [V] = DIS2 [U] + 和[V]。 q.push(make_pair(DIS2 [V]、V))。 } } } } int型のmain() { scanf関数(" %D%dの"、&N、&M)。 以下のために(int型私= 1 ; I <= M、I ++) { int型X、Y。 scanf関数(" %dの%のD "、およびX&Y)。 (x、y)を加えます。 } のために(int型 I = 1は iが++; iがn = < ) { 場合(!DFS(I)DFN [I])。 } // のmemset(プリ、0、はsizeof(PRE))。 以下のために(int型 i = 1 ; iが++; iが<= N ) { [[i]が属する]和 ++ 。 } // ため(INT I = 1; I <= QW; iは++)のprintf( "%dの"、和[I])。 以下のための(int型 I = 1;私は++; iが<= N ) { ため(INT P; P = P =最後[i]が予め[P]) { int型 V = 他の[P]。 もし(![I] =属し[V]属する) { ADD0([I]、[V]属する属します)。 ADD2([I]属し、[V]属します)。 } } } ANS =和[属する[ 1 ]。 ダイクストラ(属し[ 1 ])。 dijkstra2([属する1 ])。 // (I = 1をint型、iが<= N; iが++)のためのprintf( "%dの"、DIS1 [I])。 memsetの(VIS、0、sizeof (VIS)); 以下のために(int型 I = 1は iが++; iは= <N ) { 場合(VIS [属し[I] || DIS1 [属する[i]は]!)続けます。 VIS [i]は、[所属] = 1 ; int型のx = 所属[i]は、 用(INT P = last2 [X]; P; P =のPRE2 [P]) { int型 V = other2 [P]。 もし(!DIS2 [V])続けます。 ANS = MAX(ANS、DIS1 [X] + DIS2 [V] -sum [属する[ 1 ])。 } } printf("%のD " 、ANS); 戻り 0 ; }