HZOI20190725 Bホームtarjan

トピックの効果:https://www.cnblogs.com/Juve/articles/11246364.html

ソリューション:

私は非常に水を感じるが、診察室を出て再生できませんでした

エンドポイントへの開始点の出力が通過しなければならない何であるかトピックを翻訳

実際には、需要がエンドポイントカットに始まります

このアルゴリズムは、非常に大きな問題であり、私は私の方法を導入しました:

55%:

このアルゴリズムは正確ではなくてもよい少なくとも55点

私たちは、tarjanダブルポイントをシークし、凝縮点

その後、我々はダブルポイント1ポイントが配置されているから、DFSが起動し、

スタックに置く点で切断二点、二点のそれぞれは、検索が続く、スタックを維持

後ろにポップするとき、我々は2点の数nのポイントを発見した際に、検索を停止

私たちは、その点を尋ねるように、残りの点を積み重ねます

 

#include <iostreamの> 
する#include <cstdioを> 
する#include <CStringの> 
する#include <アルゴリズム> 
の#include <ストリング> 
の#include <ベクトル> 
の#include <スタック> 
の#define MAXM 4000005 
の#define MAXN 2000005 
の#define LL長い長
の#defineレジスタの再
名前空間stdを使用。
インライン読み取り11(){ 
    LL再X = 0;チャーCH = GETCHAR()。
    ;(CH < '0' || CH> '9'){CH = GETCHAR()}ながら
    、一方(CH> = '0' && CH <= '9'){X =(X << 1)+(X << 3)+ CH-'0' ; CH = GETCHAR();} 
    戻りX; 
} 
LL T、N、M。
[MAXM << 2]、NXT [MAXM << 2]、あらかじめ[MAXN]、CNT = 0〜LL 
インラインボイドは、(U LL再追加します 
    再II){ CNT ++ [CNT]がV =を、NXT [CNT]は[U] = CNT、[U]を=。
}
LL版[MAXM << 2]、nxtt [MAXM << 2]、ヘッド[MAXN]、和= 0。
{(U、再用のLL V LL RE)インラインボイドADD 
    [和]版和++、= V、nxtt [和] =頭部[U]、ヘッド[U] =合計。
} 
LL DFN [MAXN]、低[MAXN]、dfs_order = 0、STA [MAXN]、トップ= 0、dcc_num = 0、属する[MAXN]。
BOOL is_cut [MAXN]。
ベクター<LL> DCC [MAXN]。
インラインボイドtarjan(再LL X){ 
    DFN [x]はロー= [X] = ++ dfs_order。
    STA [++トップ] = xと; 
    LLのNUM = 0。
    {(; iはi = NXT [i]はLL再I = [X] PRE)のための
        LL Y再= [I]に。
        IF(DFN [Y]!){ 
            tarjan(Y)。
            低[X] =分(低[x]は、低[Y])。
            IF(低[Y]> = DFN [X]){ 
                NUM ++、dcc_num ++。
                IF(!X = 1 || NUM> 1)is_cut [X] = 1。
                LL Z再。
                実行{
        {(J ++; J <N LL J = 0)のための
                    Z = STA [top--]。
                    DCC [dcc_num] .push_back(Z)。
                }一方、(Y = Z!)。
                DCC [dcc_num] .push_back(X)。
            } 
        } 
        そうでなければ低[X] =分(DFN [Y]、[x]は低いです)。
    } 
} 
スタック<LL>。
LL TOT = 0、NUM = 0、NEW_ID [MAXN]。
ブールフラグ= 0は、[MAXN] ANS。
ボイドDFS(LLのX、LL FA){ 
    (x == [n]が属する){もし
        フラグ= 1。
        返します。
    } 
    のための(LL I =ヘッド[X]; I; I = nxtt [I]){ 
        IF(版[I] == FA)続けます。
        Y LL = [Y] .size()N [I]版= DCC。
            IF(is_cut [DCC [Y] [J]]){ 
                // COUT << DCC [Y] [J] << ENDL。 
                a.push(DCC [Y] [J])。
            } 
        } 
        DFS(Y、X)。
        (フラグ)戻った場合。
    } 
    //cout<<a.top()<<endl。
    (もし!a.empty())a.pop(); 
} 
(){主署名された
    T =を読み取ります()。
    一方、(T - ){ 
        N =)(読み取り、M = read()は、
        {(; I <= M I ++はi = 1 LL再U、V)のために
            Uが読み取ら=()、V =(読み取り)
            (uは== v)を続ける場合は、
            追加(u、v)は、追加(V、U); 
        } 
        tarjan(1)。
        NUM = dcc_num。
        (私は++; iが<= N LL再I = 1)のための
            (is_cut [I])NEW_ID [I] = ++ NUMであれば、
        ため(再LL I = 1; I <= dcc_num; iは++){  
            )LL N = DCC再[I] .size(。
            ため(LL再J = 0であり、j <N; J ++){ 
                LL tの再= DCC [I] [J]。
                IF(is_cut [T]){ 
                    ADD(I、NEW_ID [T])。
                    ADD(NEW_ID [T]、I)。
                    属する[T] = NEW_ID [T]。
                }そう[T]属する= I。
            } 
        } 
        //ための式(I ++はLL i = 1; iが<= N)
        // COUT << I <<」「<<属し[I] << ENDL。
        // coutの<< "------------------------" <<てendl; 
        //のための(LL i = 1; iが<= NUM iは++){ 
        (; J;のLL J =ヘッド[i]はJ = nxtt [J])//用{ 
        // COUT << I <<」「< <版[J] << ENDL。
        DFS(0、[1]に属します)。
            再LL TP = a.top()。
            a.pop(); 
            (!ANS [TP]){もし
                あれば(!TP = 1つの&& TP = N){ 
                    ANS [TP] = 1。
                    TOT ++; 
                } 
            } 
        } 
        のprintf( "%LLDする\ n"、TOT)。
        (; iがn <; LL I = 2 iが++)のための
            IF(ANS [i])と
                のprintf( "%のLLD"、I)。
        プット( ""); 
        memsetの(前、0、はsizeof(PRE))。
        CNT = dfs_order = TOT = dcc_num =合計= NUM = 0; 
        memset(DFN、0、はsizeof(DFN))。
        memset(is_cut、0、はsizeof(is_cut))。
        memset(DCC、0、はsizeof(DCC))。
        memsetの(頭、0、はsizeof(ヘッド))。
        memset(ANS、0、はsizeof(ANS))。
        フラグ= 0。
    } 
    0を返します。
} 
/ * 
15 19 
1 2 
1 3 
1 12 
12 13 
13 14 
12 14 
2 4 
3 4 
4 6 
4 5 
6 5 
5 7 
5 8 
7 8 
7 9 
8 9 
9 15 
15 11 
15 10 

4 3 
1 2 
2 3 
3 4 
 
5 
1 2 
2 3 
3 4 
4 
4 1 
 
5 
1 2 
2 3 
3 4 
4 5 
5 1 
* /

 

何が問題なの?なぜ55分がありますか?説明兄がありますが、あなたはメッセージを残すことができます

別のアルゴリズム:

このアルゴリズムは90点でしたが、問題を見つけることができませんでした(ギャングスターが提案されています)

私たちは、途中記録パス、ダイクストラまたはspfaで1からnまで実行最短

これは、この道路上の特定のポイントを通過しなければなりません

だから私たちは橋の両側を埋めるために、ポイントポイントの要件はでき

100%:

実際には、単にA上の点を削減するボードtarjanに単語を追加します。

カット点判定、DFNを添加した後判定条件【には、[i]は<= DFN [N]とすることができる場合

 

1  であれば(低[Y]> = DFN [X] && DFN [Y] <= DFN [N]){
 2      NUM ++ 3      であれば(X =!1 || NUM> 1 [X] = is_cut)1、TOT ++ 4 }

 

原理tarjanの実現について考え、DFN [n]はDFNの最後の値であり、

、ノードyがnよりも大きい場合、我々はその後、DFN値を発見したN Yが優先するために見つけることが必ずあります

そして、私たちは1つのDFSから始めて、それが道路を通過しなければならない1のn yに確かにあります

この質問は上そんなに水であります

書式#include <iostreamの> 
の#include <cstdioを> 
する#include <CStringの> 
の#include <アルゴリズム> 
書式#include <文字列> 
に#define MAXM 400005 
の#define MAXN 200005 
の#defineは長い長いっ
の#define再登録
std名前空間を使用しました。
インライン読み取り11(){ 
	LL再X = 0;チャーCH = GETCHAR()。
	;(CH < '0' || CH> '9'){CH = GETCHAR()}ながら
	、一方(CH> = '0' && CH <= '9'){X =(X << 1)+(X << 3)+ CH-'0' ; CH = GETCHAR();} 
	戻りX; 
} 
LL T、N、M。
[MAXM << 1]、NXT [MAXM << 1]、プリ[MAXN]、CNT = 0〜LL 
インラインボイド{(LL V再、LL U RE)を追加
	、CNT ++ [CNT]にV、NXT [CNTを] = = [U]を事前に、[U] = CNTを事前。
} 
LL DFN [MAXN]、低[MAXN]、dfs_order = 0、TOT = 0。
BOOL is_cut [MAXN]。
インラインボイドtarjan(再LL X){ 
	DFN [x]はロー= [X] = ++ dfs_order。
	= 0 LL NUM再。
	{(; iはi = NXT [i]はLL再I = [X] PRE)のための
		LL Y再= [I]に。
		IF(DFN [Y]!){ 
			tarjan(Y)。
			低[X] =分(低[x]は、低[Y])。
			IF(低[Y]> = DFN [X] && DFN [Y] <= DFN [N]){ 
				NUM ++。
				[X] = 1、TOT ++ is_cut IF(!X = 1 || NUM> 1)。
			} 
		} 
		そうでなければ低[X] =分(DFN [Y]、[x]は低いです)。
	} 
} 
(){主署名された
	T =を読み取ります()。
	一方、(T - ){ 
		N =)(読み取り、M = read()は、
		{(; I <= M I ++はi = 1 LL再U、V)のために
			Uが読み取ら=()、V =(読み取り)
			(uは== v)を続ける場合は、
			追加(u、v)は、追加(V、U); 
		} 
		tarjan(1)。 
		のprintf( "%LLDする\ n"、TOT)。
		{(; iは<= N I ++はLL再I = 1)のために 
			IF(is_cut [i])と
				のprintf( "%のLLD"、I)。
		} 
		プット( "")。
		CNT = dfs_order = TOT = 0。
		memsetの(前、0、はsizeof(PRE))。
		memset(DFN、0、はsizeof(DFN))。
		memset(is_cut、0、はsizeof(is_cut))。
	} 
	0を返します。
}

ここでも同様の質問にloj:ZJOI 2004スニファ「3.6演習2スルー」https://loj.ac/problem/10101

あなたはこの質問は非常に水を見つけますが、出発点は1とnの終わりではありません

コード:

書式#include <iostreamの> 
の#include <cstdioを> 
する#include <CStringの> 
の#include <アルゴリズム> 
書式#include <文字列> 
の#define MAXM 2005 
の#define MAXN 1005 
の#defineは長い長いっ
の#define再登録
std名前空間を使用しました。
LL、B、N、U、V、ANS = 0x7FFFFFFFで。
[MAXM << 1]、NXT [MAXM << 1]、プリ[MAXN]、CNT = 0〜LL 
インラインボイドは、{CNT ++(LL V再、LL U RE)追加[CNT]にV、NXT [CNTを] = = [U]を事前に、[U] = CNTを事前。} 
LL DFN [MAXN]、低[MAXN]、dfs_order = 0、TOT = 0。
BOOL is_cut [MAXN]。
インラインボイドtarjan(再LL X){ 
    DFN [x]はロー= [X] = ++ dfs_order。
    = 0 LL NUM再。
    用(; iは、LL再I = [X]事前I = NXT [I]){
        IF(DFN [Y]!){
            tarjan(Y)。
            低[X] =分(低[x]は、低[Y])。
            IF(低[Y]> =のDFN [X] && DFN [Y] <= DFN [B]){ 
                NUM ++。
                (!X = ||> 1数値)であれば
                    TOT ++、ANS =分(ANS、x)は、
            } 
        }そうでなければ
            低[X] =分(DFN [Y]、[x]は低いです)。
    } 
} 
(){主符号付き
    のscanf( "%のLLD"、&N); 
    しばらく(〜のscanf( "%のLLDの%のLLD"、&U&V)){ 
        場合(U + V == 0)
            ブレーク。
        追加(u、v)は、追加(V、U); 
    } 
    のscanf( "%のLLDの%のLLD"、&、&B)。
    tarjan(A)。
        printf( "%LLDする\ n"、ANS)。
        プット(「ノーソリューション」); 
    0を返します。
}

 

おすすめ

転載: www.cnblogs.com/Juve/p/11246522.html