네트워크 UVA - (315) (도 통신 요청 인하 점)

#INCLUDE <STDIO.H> 
#INCLUDE <알고리즘> 
#INCLUDE <iostream> 
#INCLUDE < 문자열 .H>
 은 USING  공간 STD; 

/ * 
* 절삭 점 아무런 요청도 다리 
* 커트 포인트를 찾을 수 있고, 다리, 시크 통신 차단 삭제 각 포인트 증가 후에. 
* 무거운 가장자리 처리가 상기 제 1 행렬이 저장 될 수 있음을, 인접하는 서브 테이블 또는 재 차익 주 
* / 
CONST  INT MAXN = 10010 ;
 CONST의  INT MAXM = 100010 ;
 구조체 에지 
{ 
    INT 에 다음,
     BOOL 컷; // 플래그 다리 여부 
} 에지 [MAXM]
 INT의 헤드 [MAXN, TOT,
 INT낮은 [MAXN, DFN [MAXN, 스택 [MAXN]
 int로 색인, 최고,
 BOOL Instack [MAXN]
 BOOL 컷 [MAXN]
 INT add_block [MAXN]; // 통신 지점 블록 제거한 후 추가 
INT의 다리 ; 

공극 addedge ( INT U, INT의 V) 
{ 
    에지 [TOT] .TO = V, 에지 [TOT] 헤드 다음 내용 = [U] 엣지 [TOT = .CUT false로 , 
    헤드 [U] = TOT ++ ; 
} 


무효 Tarjan ( INT U, INT 사전) 
{ 
    INT의 V, 
    낮은 [U] = DFN [U] ++ = ++] = 인덱스;
    스택 [상부 U; 
    Instack는 [U]는 = ;
    INT의 아들 = 0 ;
    위한 ( int로 -;! I = I = 헤드 [U]가 1 , I = 가장자리 [i]는 다음 내용) 
    { 
        V = 에지 [I] .TO;
        경우 (V == 사전이) 계속 ;
        만약 (! DFN [V]) 
        { 
            아들 ++ ; 
            Tarjan (V U, 께); 
            경우 (저 [U]> 로우 [V]) 로우 [U] = 낮음 [V];
            // // 무향 에지 만 (u, v)가 곁가지이고, DFS (U) <저를 만족한다면 (U는 V)와, 다리 (V ).
            IF (낮음 [V]> DFN [U]) 
            { 
                다리 ++ ; 
                에지 [I] .CUT = true로 , 
                에지 [I ^ 1. ] = .CUT true로 ; 
            } 
            // 커트
             // 정점은 유 커트 포인트 만족할 경우에만, (1) 또는 (2) (1) U 루트이고, u는 하나 이상의 서브 트리를 갖는다.
            @ 2 U는 루트 (U, V) 인 사이드 브런치 (또는 친자 가장자리의 존재를 만족하지 않다
             // 즉, U 및 검색 트리 V 아버지)되도록 DFS (U) <= 낮음 (V) 
            IF (U = 로우 프리 && [V]> = DFN [U]!) // 하지 루트 
            { 
                컷 [U]가 ;= 
                add_block [U] ++ ; 
            } 
        } 
        다른  경우 (저 [U]> DFN [V]) 
            낮음 [U] = DFN [V]; 
    } 
    // 树根,分支数大于한 
    경우 (U == 사전 && 아들> 1 ) 컷 [유] = ;
    만약 (U == 전) add_block [U] 아들 = - 1 ; 
    Instack는 [U]는 = 거짓 ; 
    최고 - ; 
} 

공극은 해결 ( INT의 N) 
{ 
    memset 함수 (DFN, 0 , (DFN));를 sizeof 
    memset 함수 (Instack, 거짓 , 는 sizeof (Instack)); 
    memset 함수 (add_block, 0 , 는 sizeof (add_block)); 
    memset 함수 (잘라 내기, 거짓 , 는 sizeof (컷)); 
    지수 = 정상 = 0 ; 
    다리 = 0 ;
    위한 ( int로 I = 1 , N = 1이 <; 내가 ++ )
         경우 (! DFN [I]) 
            Tarjan (I, I); 
    INT ANS = 0 ;
     ( INT I = 1; 나는 = <N; ++ i가)
         경우 (절단 [I]) 
            ANS ++ ; 
    의 printf ( " % D \ 없음 " , ANS); 
} 
공극 초기화 () 
{ 
    TOT = 0 ; 
    memset 함수 (머리 - 1 , 를 sizeof (헤드)); 
} 

INT 의 main () 
{ 
    INT의 N;
    반면 (는 scanf ( " %의 D ' , N), N) 
    { 

        int로 A, B 단계;
        숯불 채널; 
        초기화 (); 
        반면 (는 scanf ( " % d의 " , & A ) a) 
        { 
            동안 (는 scanf ( " % d 개 %의 C ' , B, CH)) 
            { 
                addedge (a, b); 
                addedge (b, a); 
                경우 (CH2 == ' \ n ' )
                     분해 ; 
            } 
        } 
        (N) 해결; 
    } 
    반환  0 ; 
}

 

추천

출처www.cnblogs.com/smallhester/p/11259383.html