2019 멀티 - 대학 교육 경연 대회 1 개 경로 (최소 컷 최단 +)

질문의 의미 : 짧은 길이가보다 n을 방법 1의 이동을 만드는 방법을 물어 있도록 가장 저렴한 방법의 일부를 차단할 수 있습니다 이제 N 포인트 m 가장자리를 줄

아이디어 : 최단 시작을 구축하고 대부분의 단락 회로 다이어그램과 동시에 우리의 최대 유량 최소 잘라 내기 요구하면서 실행보고

#INCLUDE <비트 / stdc ++ H.>
 사용  스페이스 성병;
CONST  이중 PI ACOS = (- 1.0 );
CONST의  INT maxn 1E4 + = 7 ;
CONST  INT INF = 0x3f3f3f3f ;
CONST   EPS 1e- = 6 ; 
타입 정의  LL;
CONST LL 모드 1E9 + = 7 ;
구조체 에지 {
     int로 , 옆; w LL; 
}; 
에지 E [maxn << 1 ];
INT의 헤드 [maxn, CNT;
INT힘 [maxn]; 
LL의 D [maxn]; 
공극 초기화 () { 
    CNT = 0 ; 
    memset 함수 (헤드, 0 , 는 sizeof (헤드)); 
    memset 함수 (힘, 0 , 는 sizeof (힘)); 
    memset 함수 (d, INF, 는 sizeof (d)); 
} 
공극 추가 ( int로 U, INT의 V, INT w) { 
    E [ ++ CNT] = {헤드 [U, V, W}; 
    헤드 [U] = CNT; 
} 
공극 DIJ ( INT의 S) { 
    priority_queue <쌍 <LL, INT >>큐; 
    D [S] = 0 ; 
    q.push (make_pair ( 0 , S));
    반면 (! {q.empty ())
         INT U = q.top () 제.; 
        q.pop (); 
        경우 (힘 [U]) 계속 ; 
        힘 [유] = 1 ;
        위한 ( int로 ; I I = I = 헤드 [유] {E [i]는 다음 내용)
             의 INT V = E가 [I] .TO; INT w = E [I] .W;
            경우 (d는 [V]>는 D [U]는 + w) { 
                D는 [V] D [U] + = w 단계; 
                q.push (make_pair ( -D [V] V)); 
            } 
        } 
    } 
} 
구조체의 가장자리 { 
  LL 에서 , 캡, 흐름; 
  에지 ( int로 U, INT의 V, INT의 C, INT의 F) (U), (V), 캡 (c) 흐름 (F) {} 
}; 

구조체 Dinic {
   INT의 N, M, S, T; 
  벡터 <엣지> 에지; 
  벡터 < INT > G [maxn];
  INT D [maxn 같이, [maxn] CUR;
  불리언 힘 [maxn]; 

  무효화 INIT ( INT의 {N)
    위한 ( int로 I = 0 ; I <N이 나 ++ G [I]하는 명확한 ())를; 
    edges.clear (); 
  } 

  공극 AddEdge ( INT  에서 , INT 에, INT의 CAP) { 
    edges.push_back (에지 (  에, 캡, 0 )); 
    edges.push_back (에지에 (  , 0 , 0 )); 
    m = edges.size (); 
    G [  ] .push_back (m - 2 ); 
    .push_back [을] G (m - 1 ); 
  } 

  부울BFS () { 
    memset 함수 (마주, 0 , sizeof 연산자 (마주));  < INT > Q; 
    Q.push (S); 
    D [S] = 0 ; 
    힘 [S] = 1 ;
    반면 (! Q.empty ()) {
       INT (X) = Q.front (); 
      Q.pop (); 
      위한 ( int로 I = 0 ; I <는 G를 [X] 크기는 (); 나는 ++ ) { 
        에지 및 E = 가장자리 [G [X] [I];
        만약 (! 힘 [e.to] && e.cap> e.flow) { 
          힘 [e.to] =1 ; 
          D [e.to] = D [X] + 1 ; 
          Q.push (e.to); 
        } 
      } 
    } 
    복귀 힘 [t]을; 
  } 

  LL DFS ( INT의 X, LL a) {
     경우 (X == t || == 0 ) 돌려 단계; 
    LL 흐름 = 0 , F;
     ( INT 및 I = CUR [X] 난 <G를 [X] 크기는 (); 나는 ++ ) { 
      에지 및 E = 가장자리 [G [X] [I];
      경우 (d [X] + 1 == D [e.to] && (F = DFS (e.to, 분 (a, e.cap - e.flow)))> 0 ) {
        e.flow + = F; 
        에지 [G [X] [I]를 ^ 1 ] .flow - = F; 
        흐름 + = F 단계; - = F;
        경우 (A == 0 ) 체류 ; 
      } 
    } 
    리턴 흐름; 
  } 

  LL Maxflow ( INT S, INT의 t) {
     이것 -> S에서의 = S;
     -> t = t; 
    LL 흐름 = 0 ;
    반면 (BFS ()) { 
      memset 함수 (현재, 0 ,를 sizeof (현재)); 
      흐름 + = DFS (S, INF); 
    } 
    리턴 흐름; 
  } 
} dinic; 
INT 비안 [maxn] [ 3 ];
INT 의 main () {
     INT의 t; 
    scanf와 ( " %의 D " , t);
    반면 (t-- ) { 
        초기화 (); 
        INT의 N, m; 
        scanf와 ( " %의 D % d에 " , N, m);
        위한 ( int로 난 = 1 ; I <= m 내가 ++ ) {
             INT X, Y, C; scanf와 (" % D % D % D ' , X, Y, 및 C); 
            비안 [I] [ 0 ] = X를; 비안은 [I]는 [ 1 ] = y로; 비안 [I] [ 2 ] =의 C; 
            추가 (X, Y, C); 
        } 
        DIJ ( 1 ); 
        dinic.init (N); 
        위한 ( int로 I = 1 ; I <= m; 내가 ++ ) {
             경우 (d [비안 [I] [ 1 ]] == D [비안 [I] [ 0 ] + 비안 [I] [ 2 ]) { 
                dinic .AddEdge (비안 [I] [ 0 ], 비안 [I] [ 1 ], 비안 [I] [ 2 ]); 
            }
        }
        의 printf ( " % LLD \ 없음 " , dinic.Maxflow ( 1 , N)); 
    } 
}
코드보기

 

추천

출처www.cnblogs.com/wmj6/p/11348247.html