나무와 꽃 알고리즘 : 일반 그래프 최대 매칭

그래프를 들면 G ( V , E ) 하는 일치,M은 튜플 ( U , V ) 세트 이들 상기 U , V V,(U, V) ∈E하고,M이 존재하지 않는 중복 지점.

| 남성 | 큰 시간, 우리가 전화를 M을G의 최대 일치.

경우 G는 최대 매칭 고전 헝가리어 알고리즘 또는 네트워크 흐름 알고리즘을 사용하여 해결 될 수있다 된 그래프이다. 그러나,G는 직접 증강 일반보기가 가능하게하고,이 시간 우리는 일치하는 작업을 완료하는 나무와 꽃 알고리즘을 사용합니다.

1 #INCLUDE <cstdio>
 2 #INCLUDE <cctype>
 3 #INCLUDE <CString을>
 4 #INCLUDE <알고리즘>
 5  이용  공간을 성병;
6  INT의 판독 () {
 7      INT X = 0 , F = 1 ;
8      문자 C = getchar가 ();
9       (; isdigit에 (c) C = getchar가 (!)에서) 경우, (c == ' - ' ) F = - 1 ;
10       (; isdigit에 (c) C = getchar가 ()) X = X * 10 + C- ' 0 ' ;
11       X * F;
12  }
 13  CONST  INT maxn = 505 ;
14  CONST  INT의 MAXM = maxn maxn * * 2 ;
15  INT N, m, 가야가 [MAXM, QL은 QR은 [maxn] 미리 팀 = 0 ;
16  구조체 에지 {
 17      INT의 V, NXT;
18  } E [MAXM];
19  INT H [maxn, TOT = 0 ;
20  INT 매치 [maxn], F [maxn, TP [maxn, TIC [maxn];
21  INT 찾기 ( INT X) {
 22      반환F [X] == X F [X] : F [X] =? 발견 (F [X]);
23  }
 24  무효 추가 ( int로 , U를 INT V)를 {
 25      E [++ TOT] = (에지) {V, H [U]};
26      H [U] = TOT;
27  }
 28  INT의 LCA ( INT의 X, INT Y) {
 29       (++ 팀; 스왑 (X, Y)) 의 경우 (X) {
 30          X = 발견 (X);
31 일          경우 (TIC [X] == 팀)  X; 다른 TIC [X] = 팀, X = 프리 [매치 [X];
32      }
 33 }
 34  무효 수축 ( INT의 X, INT Y, INT의 P) {
 35      동안 ((x)를 발견! = P) {
 36          미리는 [X]는 = Y는, Y가 = 일치 [X];
37          의 경우 (TP [Y] == 2 ) TP [Y] = 1 , 케 [++ QR = Y;
38          의 경우 F ((x)는 X == 찾기)을 [X] = P;
39          의 경우 (찾기 (Y) == Y) [Y] F = P;
40          X = 프리 [Y];
41      }
 42  }
 43  부울 8월 ( INT S) {
 44      ( INT가 나는 = 1 ; I <= N; ++ I) F [I] = I;
45      memset 함수 (TP, 0 , sizeof 연산자 TP)가 memset (미리 0 , 는 sizeof 사전);
46      TP [케 [QL = QR = 1 ] = S = 1 ; // 1 : A 형; 2 : B 형 
(47)      의 INT t = 0 ;
48      동안 (QL <= QR) {
 (49)          INT (X) = 케 [QL ++ ];
50           ( 하는 int i가 H가 = [X], V = E [I] .V 내가, 내가 전자 = [I] .nxt, V = E [I] .V) {
 51              하다면((V)를 찾아 찾아 == (X) || TP [V] == 2 ) 계속 ; 
(52)              만약 (! TP [V]) {
 53                  (TP)는 [V] = 2 , 미리 [V] = X;
(54)                  만약 (! 매치 [V]) {
 55                       ( INT 지금 = V, 마지막 TMP는, 지금, 지금 = 마지막) {
 56                          마지막 = 일치 [TMP가 = [전 이제];
(57)                          검색 [현재] = TMP 경기 [TMP = 이제;
58                      }
 59                      반환  ;
60                  } 
 61                 TP [매치 [V] = 1 , 케 [++ QR = 매치 [V];
62              } 다른  경우 (TP [V] == 1 ) {
 63                  INT의 L = LCA (X, V);
(64)                  수축 (X, V, l);
(65)                  수축 (V, X, l);
66              }
 67          }
 68      }   
 69      반환  거짓 ;
70  }
 71  INT 의 main () {
 72  ONLINE_JUDGE #ifndef
 73      freopen을 ( " test.in " , "R " 표준 입력)
 74 개      freopen을 ( " my.out " , " w " , 표준 출력)
 75  #endif 다음 
76      N = (판독), m = ) (읽기,
 77       ( INT는 난 = 1 I <= m; ; ++ I) {
 78          INT (X) = (판독), Y는 = () 읽기,
 79          추가 (x, y)에, 추가 (Y, X)
 (80)      }
 (81)      INT ANS = 0 ,
 82       ( INT I = 1 ; I <= N; ++ I) + = ANS (매치 [I] &&! 8월 (I));
83      의 printf ( " 가 % d \ n " , ANS);
84       ( INT 나 = 1 ; i가 <= N; ++ I)의 printf ( " %의 D " 경기 [I]);
85      풋 ( "" );
86      반환  0 ;
87 }

원본 제목은 UOJ79이다, ANS i 번째 개인의 배우자 예를 나타내는 경기의 최대 번호, 경기는 [I]입니다.

 

추천

출처www.cnblogs.com/St-Lovaer/p/11945534.html