タイトル
分析:
元のタイトルをポイントは直接接続されていない全ての辺は一緒に座ることができるためにも指し、マーキング図を補完するために変換されます。
それはそれぞれのV-DCC DFSのための奇妙なリングが含まれている場合は、その後、リングの多くのビューに変換し、疑問点が奇数のリングで必要とされていない、再度、参照してください。
DCCは奇妙なリングが含まれている場合は、DCC内のすべての点は、少なくとも奇妙なリング上にあります。
証明:
DCC少なくとも1つの環、および環上の2つの特異点が含まれている必要があり、この環上の各点は、環上の奇数の2点が特異点を有する環を形成することができます。
受刑奇妙リング:
二点間のような色のエッジが特異リングにトラバース説明したとしても、各点に色、。
好ましくは、選択された色点1と2、注意初期値。
ボイド DFS(INT U、INT COL、INT 今) { C [U] = COL。 用(RI I =ヘッド[U]; I; I = NEX [I]){ int型 V = 乃至[I]。 もし(ベル[V] =今!)続けます。 もし(C [V] && C [V] == C [U]){FL = 1。返します。} もし(!C [V])DFS(V、3今-col)。// 1 2 COL } }
tarjanはダブルポイント、カットポイントテンプレートを求めて:
用(RI i = 1 ; I <= N; ++ I)の場合(!tarjan(I、I)[I] DFN)。 ボイド tarjan(INT U、INT RT) { [U] DFN [U] = ++のTi =低いです。STKの[++トップ] = U。 もし(U == RT &&ヘッド[U] == 0 ){ DCC [ ++ CNT] .push_back(U)。 返します。 } のための(RI I =ヘッド[U]; I; I = NEX [I]){ int型、V = [I]であり; もし(!{[V] DFN) tarjan(V、RT)。 低[U] =分(低[U]、低[V]); IF(DFN [U] <= 低[V]){ IF(FL> 1。 || RT = Uは!)切り取り[U]は= trueに ; // 分析カット点 CNT ++; int型TMP; DO { TMP = STK [上]、 トップ - ; DCC [CNT] .push_back(TMP); } ながら(!TMP = V); DCC [CNT] .push_back(U); // Uは二重で追加された自身の間に覚え } } そうでなければ低[U] =分(低[U]、DFN [V])。 } }
完全なコード:
#include <ビット/ STDC ++ H> 使用して 名前空間STDを、 #define N 1005 の#define M 1000005 の#defineは、 INTレジスタRI INT STK [N]、トップ= 0 、ベル[N]、低[N]、DFN [N]、N、M、嫌い[N]、[N]を[N]ができます。 INT TOT = 0、ヘッド[N]、NEX [M]は、[M]にはTi = 0、CNT = 0は、[N] C、[N]を切断します。 ベクター < INT > DCC [N]。 ボイド追加(INT A、INT B){[++ TOT = Bへ; NEX [TOT =ヘッド[A]。ヘッドは、[A] = TOTを、} ボイドのinit() { TOT = 0Ti = 0、CNT = 0 。 memset(憎悪、0、はsizeof (憎悪))。 用(RI i = 1 ; I <= N; ++ I)缶[I] =低[I] =のDFN [I] =のSTK [I] =頭部[I] =のC [I] =ベル[I] = 0 、DCC [I] .clear(); } ボイド tarjan(INT U、INT RT) { [U] DFN [U]は= ++のTi =低いです。STKの[++トップ] = U。 もし(U == RT &&ヘッド[U] == 0 ){ DCC [ ++ CNT] .push_back(U)。 返します。 } のための(RI I =ヘッド[U]; I; I = NEX [I]){ int型の V = [I]へ。 もし(!{[V] DFN) tarjan(V、RT)。 低[U] = 分(低[U]、[V]低いです)。 もし(DFN [U]は<= 低い[V]){ 場合(FL> 1!|| U = RT)カット[U] = 真。// 判断割点 CNT ++; int型TMP; 実行{ TMP = STK [トップ]。 トップ - ; DCC [CNT] .push_back(TMP)。 } しばらく TMP(!= V)。 DCC [CNT] .push_back(U)。// U记得把它本身也加入点双之间 } } そうでなければ低[U]は= 分(低[U]、DFN [V])。 } } int型のFL。 ボイド DFS(INT U、INT COL、INT 今) { C [U] = COL。 用(RI I =ヘッド[U]; I; I = NEX [I]){ int型 V = 乃至[I]。 もし(ベル[V] =今!)続けます。 もし(C [V] && C [V] == C [U]){FL = 1。返します。} 場合DFS(V、(C [V]!)3今-col)。// 1 2 COL } } int型(メイン) { int型、B。 一方、(1 ){ scanf関数(" %D%dの"、&N、&M)。 もし(N == 0 && m個の== 0)ブレーク。 初期化(); 用(RI i = 1 ; I <= M; ++ I)のscanf(" %d個の%のD "、&、&B)、嫌い[A] [B] = 1、嫌い[B] [A] = 1 。 用(RI i = 1 ; iが<= N; ++I) のために(ロードアイランドJ = + 1、J <= N; ++ j)の 場合(![I] [J])嫌い )、J(Iを、(i、j)を追加。 用(RI i = 1 ; I <= N; ++ I)の場合(!tarjan(I、I)[I] DFN)。 / * のための(RI i = 1; iは= CNT <; ++ I){输出点双 のprintf( "I:%Dを\ n"、I)。 (ロードアイランドJ = 0; jは<DCC [I] .size(); ++ j)のためのprintf( "%dの"、DCC [I] [J])。 } * / 用(RI i = 1 ; iは= CNTを<; ++ I){ FL = 0 。 用(RI J = 0 ; J <DCC [I] .size(); ++ j)は ベル[DCC [I] [J] = I、C [DCC [I] [J] = 0 ; DFS(DCC [I] [ 0 ]、1 、I)。 もし(FL){ 用(ロードアイランドJ = 0 ; J <DCC [I] .size(); ++ j)は 缶[DCC [I] [J] = 真。 } } int型 ANS = 0 。 用(RI i = 1 ; I <= N; ++ I)の場合(!缶[i])とANS ++ 。 printf(" %d個の\ n "、ANS)。/ ** / } リターン 0; } / * 5 1 4 1 5 2 5 3 4 4 0 0 * /