質問の意味:フリー相図を考えると、新しく追加されたエッジのQ時間は、ブリッジを追加するプロセスで辺の数を求め
た場合とエッジする時間(u、v)は分岐するためには、DFN(U)を満たすために必要ではない場合にのみ<低い(V)、
即ちU未満、Vは点以上上がって、UV間に1つのまたは複数のエッジを有することができなければならない、省略されていないため、それらの間のリングのない部分、ブリッジの
アイデア:まず、マップ、側面を追加し続ける与えられた後に、ブリッジの数は減らすのではなく増加することがわかっている
tarjanの使用は、その後連結成分のエッジがないので、ポイント、ポイントに縮小連結成分を縮小してブリッジされ
、同時に新た側ブリッジツリーを形成し、実際には、我々は見つけるポイントを凝縮した後に終了し
、それが減少していない場合には、添加中に連結成分におけるブリッジの数を
Uと、異なる2におけるVを次いで、U、V及びそのLCA(最下位共通祖先は)新しい連結成分を形成するループに接続される通信コンポーネント、
ブリッジ部分のこの全体のセクションの全ての数はそれほど接続減少します
完全なコード:
#include <iostreamの> する#include <cstdioを> する#include <CStringの> する#include <cmath> の#include <アルゴリズム> の#include <ベクトル> の#include <積層> 使用して 名前空間STD。 typedefの長い 長いLL。 typedefのペア < int型、int型 > PII。 constの ダブル EPS = 1E- 8 ; const int型 INF = 0x3f3f3f3f 。 const int型 MAXN = 1E5 + 10 。 const int型max_edge = 4E5 + 5 。 構造体のエッジ { INT 次へ。 }エッジ[max_edge]。 int型のトップ、ヘッド[MAXN]。 INT [MAXN]事前; int型のID、DFN [MAXN]、低[MAXN]。 int型のCNT; int型のブリッジ[MAXN]。 INTのN、M。 ボイド追加(INT U、INT V){ エッジ[トップ] .TO = V。 エッジ[トップ] .next = 頭部[U]。 ヘッド[U] =トップ++ 。 } ボイド tarjan(int型のx、int型F){ // 更新タイムスタンプ DFN [X] =低[X] ++ = ; ID のための(int型 ;〜I I = I =ヘッド[X] {エッジ[I] .next) のint V = エッジ[I]。 もし(!{DFN [V]) ; Tarjan(V、X) プレ[V] = X; 低[X] = 分(低[V]、低[X]); // 決意条件ブリッジ なら(低[V]> DFN [X]){ 橋[V] = 1 ; CNT ++ ; } } そう IF(V =!F){ 低[X] = 分(低[X]、DFNは[V]); } } } 無効のinit(){ memsetの(低、0、はsizeof (低)); のmemset(DFN、0、はsizeof (DFN )); のmemset(橋、0、はsizeof (ブリッジ)); のmemset(ヘッド、 - 1、はsizeof (ヘッド)); CNT =人気= ID = 0 ; } ボイド LCA(INT U、int型Vが){ // 入力場合スワップ、Uに割り当てられたルート IF(DFN [U] < DFN [V])スワップ(U、V); // 最初の同じ高さの底の側が来 つつ(DFN [U]> DFNは[V]){ IF(橋[U]) CNT - 、橋[U] = 0 ; U = プレ[U]; } // 同時に双方がLCAに移動し ながら(!= U V){ IF - 、橋[U] =(橋[U])CNTを0 ; IF(橋[V])CNT - 、橋[V] = 0 ; U = プレ[U]; V = 事前[V]; } } int型のmain(){ int型のケース= 0; 一方、(CIN >> N >> M && N && M){ INIT()。 以下のために(int型 i = 0 ; iがm <; iは++ ){ int型Uを、V。 CIN >> U >> V; 追加(u、v)は、追加(V、U); } tarjan(1、1 )。 int型Q; cinを >> Q; 裁判所未満 << " ケース" << ++ケース<< " :" << てendl; U、V; CIN >> U >> V; LCA(U、V); coutの << CNT << てendl; } } 戻り 0 。 }