P2272 [ZJOI2007도 반값 통신 서브 tarjan + DP

아이디어 : $ tarjan + DP $

제출 : 1

해결 방법 : 강하게 연결 구성 요소가 먼저 크기 $을 $해야합니다 반 연결 구성 요소의 반 연결 구성 요소의 크기와 형태를해야합니다, 우리는 축소 가리 킵니다.

이러한 방법으로, 우리는 DAG $은 (한 번 갈래면이 반 연결 구성 요소가 될 수 없습니다) 새로운 $에서 가장 긴 체인 중 하나에 해당를 찾고 싶어요.

이후 쓰기 $ DFS $, $ SZ [U]는 $ 것을 나타냅니다 점의 개수가 점하는 단계를 포함하는, $ MX는 [U] U $ $ $ 가장 긴 사슬 길이, $부터 발현 된 (환원 후) TOT [U] $는 방식을 나타냅니다.

그러나이 그림이 연결되지 않을 수 있습니다.

#INCLUDE <cstdio> 
#INCLUDE <iostream> 
#INCLUDE <지도>
 #DEFINE ULL 긴 부호 길이
 #DEFINE가 긴 긴 것이다
 #DEFINE의 R 레지스터 INT
 사용  스페이스 성병;
#DEFINE 일시 정지 (위한 (R 된 I = 1; i가 <= 10000000000; I ++))
 #DEFINE freopen을 IN ( 'NOIPAK ++이다. ""R ", 표준 입력)
 #DEFINE 아웃 freopen을 ("나가자 밖으로 "," w ", 표준 출력)
 공간 FREAD {
 정적   B의 [ 1 << 15 ] * S = B * D = B; 
#ifndef JACK 
#DEFINE의 getchar가 () (S == && D (D = (S = B) + FREAD (B, 1,1- << 15 표준 입력)

인라인 INT의 g () { 
    R의 RET = 0 , FIX = 1 ; 등록  CH 단계; 동안 (! isdigit에 (CH = getchar가 ())) 수정 = 채널 == ' - ' - 1 : 수정;
    경우 (CH2 == EOF) 복귀 EOF; DO RET RET = * 10 + (CH ^ 48 ); 반면 (isdigit에 (CH = getchar가 ())); 반환 RET의 *의 수정; 
} 인라인 부울 IsEmpty 함수 ( CONST  CHAR & CH) {  (CH2 <= 36 || CH> = 127)} 
인라인 공극 GS (  *의 S) { 
    등록  CH 단계; 반면 (IsEmpty 함수 (CH = getchar가 ()));
     *의 ++ = 채널을; 반면 (IsEmpty 함수 (CH2 =! getchar가 ())); 
} 
} 사용 FREAD :: g을; 사용 FREAD :: GS를;
공간 Luitaryi {
 CONST의  INT의 N = 100,010 , M = 1,000,010 ; 
지도 <쌍 < INT , INT > BOOL > MP;
int로 N, m, 개조;
INTVR [M << 1 ], NXT [M << 1 ], 전나무 [M << 1 ] 카본 나노 튜브; 
인라인 공극 추가 ( INT U, INT V) {의 VR [++ CNT가] = V, NXT [CNT] = 전나무 [U], 전나무 [U] = CNT}
 INT의 절 [M << 1 ], NN [M << 1 ], FF [M << 1 ], CT; 
인라인 공극 adde ( INT U, INT V) {VV의 [++ CT] = V, NN [CT] = FF를 [U], FF [U]는 = CT}
 INT DFN [N], 로우 [N], (C) [N], STK [N], SZ [N], T [N], NUM, 참조 가기;
불리언 힘 [N]; 
인라인 공극 tarjan ( INT U) { 
    DFN [U]낮은 = [U] = NUM ++; STK [++ 최고] 힘을가 U = U = ;
    위한 (R = I 전나무 [U] I, I = NXT [I]) {R = 브이를 VR [I];
        만약 (! {[V] DFN) 
            tarjan (V); 
            낮은 [U] = 분 (저 [U], 로우 [V]); 
        } 다른  경우 (힘 [V]) 로우 [U] = 분 (저 [U] DFN [V]); 
    } 경우 (DFN [U] == 낮은 [U]) {
         ++ CC; R의 tmp;
        이렇게 , TMP = STK [정상] - 상단, [TMP] = CC C ++ SZ [CC], 마주 [TMP] = 거짓 ; 반면 (TMP =! U)를; 
    } 
} 
INT anss, ANS, MX [N], TOT [N]; 
인라인보이드 DFS는 ( int로 {U)의 
    힘은 [U]가 =  ; MX [U] = SZ [U], TOT [U] = 1 ;
    위한 (R = I의 FF [U] I, I = NN [I]) {R = 브이의 절 [I];
        만약 (! 힘 [V]) DFS (V);
        경우 (SZ [U] + MX [V]> MX [U]) { 
            MX [U] = SZ [U] + MX [V]; 
            TOT [U] = 된 TOT [V]; 
        } 다른  경우 (SZ [U] + MX [V] == MX [U]) 
            TOT [U] = (TOT [U] + TOT [V]) % 개조; 
    ANS} = 최대 (MX [U], ANS); 
} 
인라인 무효주 () { 
    N = g (), m = g (), 모드 = g ();
    위한 (R 난 = 1 , U는 V, I <= m; I ++) U = g (), V = g ()에 추가 (U, V);
    위한 (R 난 = 1 ; 나는 <= N; ++ ⅰ) 만약 (! tarjan (I) [I] DFN); 
    위한 (R U = 1 , U <= N; ++ U) 에 대한 (R = I 전나무 [U] I, I = NXT [I]) {R = 브이를 VR [I];
        경우 (c [U]! =의 C [V] && mp.find (make_pair (c [U], C [V])) == mp.end ()) 
             ++ t [C [V], adde (c [U], C는 [V]), MP [make_pair (c [U]는, C는 [V])] = ; 
    } 에 대한 (R은 I = 1 ; 나는 = CC를 <; I ++) 경우 (t [I] ||!의!힘 [I]) DFS (I);
    위한 (R I = 1 ; 나는 = CC를 <; I ++) 경우 (MX [I] == ANS) anss = (TOT anss + [I]) % 개조; 
    의 printf ( " 가 % d \ n을가 % d \ 없음 " , ANS, anss); 
} 
} 
주 () {서명 
    Luitaryi :: 주 (); 
    반환  0 ; 
}

2019년 7월 22일

추천

출처www.cnblogs.com/Jackpei/p/11223957.html