Dinic二部グラフマッチング|| Luogu P3386

質問面:[テンプレート]二部グラフ・マッチング

思考:Dinicは、スーパーソース(S)およびスーパーシンク(T)を構築するために、二部グラフマッチングを実現N + M + 1、N + M + 2に設定しました。

S及びN、次に正側の数と反対側を構築するためには、右側が正、抗エッジ重み値が0であり; mは、正の側と反対側を構築するためのTの数、1の重みの正側です。

N、Mの間で構築された図において同じ番号

そして、最大のフローを実行するために行ってきました。

注意:たCur SとTも更新する必要がありDinicたCur更新機能の各値を。

コード:

1の#include <cstdioを>
 2の#include <CStringの>
 3の#include <iostreamの>
 4  の#define分(A、B)((A)<(B)(A):( B?))
 5  使用 名前空間STD。
6  CONST  INT MAXN = 1050、MAXM = MAXN、MAXE = MAXM * MAXN。
7  整数 N、M、U、V、E、num_edge = - 1、edge_head [MAXN + MAXM]、Q [MAXN + MAXM]、F1、F2、発[MAXN + MAXM]。
8  INT S、T、たCur [MAXN + MAXM]。
9  構造体のエッジ{ INT に、NX、DIS;}エッジ[MAXE]。
10インライン無効 Add_edge(INT  からINTに、INT DIS){
 11      エッジ[++ num_edge] .nx = edge_head [ から]。
12      エッジ【num_edge] = .TO に、
13      エッジ【num_edge] .DISの=のDIS。
14      [edge_head から =] num_edge。
15      リターン;
16  }
 17インラインBOOL BFS(){
 18      のmemset(DEP、0はsizeof (DEP))。
19      = F2、F1 = 1 ;
20      発[S] = 1 21      Q [F 2 ++] =のS。
22      一方(F1 < F2){
 23          、INT X = Q [F1 ++ ]。
24          のためにINT!I = edge_head [X]; I = - 1 ; I = エッジ[I] .nx){
 25              のint Y = エッジ[I] .TO。
26              であれば(エッジ[I] .DIS &&発[Y] == 0 ){
 27                  発[Y] =発[X] + 1 28                  Q [F 2 ++] = Y。
29              }
 30          }
 31      }
 32      であれば(DEP [T])リターン 1 ;
33      リターン 0 ;
34  }
 35インラインINTのDFS(int型のx、int型FW){
 36      であれば(X == T)戻りFW。
37      のためにINT!; I = - &I = curが[X] 1 ; I = エッジ[I] .nx){
 38          のint Y = エッジ[I] .TO。
39          であれば(DEP [Y] ==発[X] + 1つの && エッジ[I] .DIS){
 40              のint p = のDFS(Y、分(エッジ[I] .DIS、FW))。
41              もし(P> 0 ){
 42                 エッジ[I] .dis- = P。
43                  エッジ[I ^ 1 ] .DIS + = P。
44                  リターンのp;
45              }
 46          }
 47      }
 48      リターン 0 49  }
 50インラインINT Dinic(){
 51      INT ANS = 0 52      一方(BFS()){
 53          のint TOI = N + M + 2 54          のためにint型 I = 1 CURが[I] =; I <= TOI I ++)はedge_head [I]。
55          一方int型 K =のDFS(S、1 << 30))ANS + = K。
56      }
 57の     リターンANS。
58  }
 59  INT メイン(){
 60      のmemset(edge_head、 - 1はsizeof (edge_head))。
61      のscanf(" %D%D%D "、&​​N、&M、&E);
62個の      S = N + M + 1、T = N + M + 2 63      のためにint型 i = 1 ; iが= Nを<Iは++ ){
 64         Add_edge(S、I、1 )。
65          Add_edge(I、S、0 );
66      }
 67      INT TOI = N + M。
68      のためには、int型、I = N + 1 ; I <= TOI; iは++ ){
 69          Add_edge(I、T、1 );
70          Add_edge(T、I、0 );
71      }
 72      のためのint型 i = 1 ; iは= Eを<I ++は{)
 73          のscanf(" %d個の%のD "、&​​U、およびV)。
74          もし(V> M || U> N)続けます75          V + = N。
76          Add_edge(U、V、1 )。
77          Add_edge(V、U、0 );
78      }
 79      のprintf(" %d個の\ n " 、Dinic())。
80      リターン 0 ;
81 }

で:AlenaNuna

おすすめ

転載: www.cnblogs.com/AlenaNuna/p/10959317.html