[] HAOI2017新しい都市

フェイス質問

https://www.luogu.org/problem/P3731

問題の解決策

カッティングエッジを求めることは二部グラフとすることができます。

#include <キュー> 
の#include <スタック> 
の#include <ベクトル> 
の#include <cstdioを> 
する#include <ユーティリティ> 
の#include <CStringの> 
する#include <iostreamの> 
する#include <アルゴリズム>
 の#define N 10050
 の#define M 150050
 の#define INF 1000000007
 の#define S 0
 の#define T(N + 1)
 の#define LL長い長
 の#define intを登録RI
 使用して 名前空間STDを、

INTのN、M、U [M]、V [M]。
ベクター < INT > 乃至[N]。
int型COL [N]、DFN [N]。 < INTINT > ANS [M]。

インラインint型リード(){
   int型 RET = 0、F = 0チャー CH = GETCHAR()。
  一方、(CH < ' 0 ' || CH> ' 9 ')は、f | =(CH == ' - ')、CH = GETCHAR()。
  一方、(CH> = ' 0 ' && CH <= ' 9 ')RET * = 10、RET + =(CH- ' 0 ')、CH = GETCHAR()。
  リターン F - ?RET:RET; 
} 

構造体グラフ{ 
  ベクトル < INT > ED [N]。
  ベクトル < 整数 > に、ワット。
  INT D [N]、CUR [N]。
  INT ベル[N]、DFN [N]、低[N]、CC、CNT。
  ブールイン[N]。
  スタック < 整数 > STK。
  ボイド add_edge(int型 U、int型 V、int型TW){ 
    to.push_back(V)。w.push_back(TW)。ED [U] .push_back(to.size()- 1 )。
    to.push_back(U); w.push_back( 0)。ED [V] .push_back(to.size() - 1 )。
  } 
  BOOL BFS(){ 
    キュー < INT > Q。
    memsetの(D、0x3fをはsizeof (d)参照)。
    D [S] = 0 ; q.push(S)。
    一方、(!q.empty()){
       int型のx = q.front()。q.pop();
      (RI i = 0 ; iが編<[X] .size(); iは++ ){
         int型、E = ED [X] [I];
        もし(D [X] + 1 <D [乃至[E] && W [E]){ 
          D [乃至[E] = D [X] + 1  
          ([E]に)q.push。
        } 
      } 
    } 
    戻り D [T] < INF。
  } 
  INT DFS(int型のx、int型の制限){
     場合(X == T ||限界== 0リターンリミット。
    int型の合計= 0 ; 
    (RI&I = CUR [X]; iは<ED [X] .size(); iは++ ){
       int型、E = ED [X] [I];
      もし(W [E] && D [X] + 1 ==のD [乃至[E]]){
         int型 F =DFS([E]、分(限界に、W [E]))。
        もし(!f)を続けます + = F。リミット-側= F。
        W [E] - = F。[W 1 ^ E] + = F。
        もし(!リミット)リターン合計。
      } 
    } 
    戻り値の和。
  } 
  int型dinic(){
     int型 RET = 0 一方、(BFS()){ 
      memsetの(CUR、0はsizeof (CUR))。
      RET + = DFS(S、INF)。
    } 
    戻りRET。
  } 
  のボイド tarjan(INT X){ 
    [X] DFN =低[X] = ++CC; 
    イン[X] = 1 stk.push(X)。
    (RI i = 0 ; iが編<[X] .size(); iは++ ){
       int型、E = ED [X] [I];
      もし(![E]ワット)続けますもし(DFN [乃至[E]]){
         場合(INS [乃至[E])低[X] = 分(低[x]は、DFN [乃至[E])。
      } 
      { 
        ([E]に)tarjan。
        低[X] = 分(低[x]は、低[乃至[E])。
      } 
    } 
    もし(DFN [X] == 低[X]){
       int型の {トン; ++ CNT;
      DO 
        トン = stk.top(); stk.pop(); イン[T] = 0 ; 
        ベル[T] = CNT。
      } 
      一方、(T =!X)。
    } 
  } 
} G。

ボイド DFS(int型のx、int型の){ 
  DFN [X] = 1COL [X] =のS。
  (RI i = 0 ; iが<[X] .size(); iは++ ){
     int型、Y = に[X] [I];
    もし(!DFN [Y])DFS(Y、S ^ 1 )。
  } 
} 

int型{main()の
  N)=(読み取り; M = 読み取ります();
  にとって(RI I = 1 ; I <= M; iが++ ){ 
    uは[I] =(読み取り)V [I] = (読み取り)
    [U [I]一back(V [i])とします。[V [I]一back(U [i])とします。
  } 
  のための(RI i = 1 ; iが<= N; iが++)場合(!DFN [i])とDFS(I、0 );
  (RI i = 1 ; I <= M; iは++ ){
     場合(COL [U [I])G.add_edge(U [i]は、V [i]は、1)。 G.add_edge(V [i]は、U [i]は、1 )。
  } 
  のための(RI i = 1 ; I <= N; iは++)場合(COL [i])とG.add_edge(S、I、1); G.add_edge(I、T、1 ); 
  G.dinic(); 
  (RI i = 1 ; iが++; iが<= n)の場合(!G.dfn [i])とG.tarjan(I)。
  int型 CC = 0 ;
  (RI i = 0 ; iはGwsizeを()<I + = 2 ){
     場合(G.bel [G.to [I ^ 1!] = G.bel [G.to [I]] && G.to [I ^ 1 ]> = 1 && G.to [I ^ 1 ] <= N && G.to [I]> = 1 && G.to [I] <= N &&!GWは、[I]){ 
      ANS [ ++ CC = make_pair(MIN(G.to [I ^ 1 ]、G.to [i])と、MAX(G.to [I ^ 1 ]、G.to [I]))。
    }  
  }
  ソート(ANS + 1、ANS + CC + 1 )。
  printf(" %d個の\ n " 、CC)。
  (RI I = 1のprintf(; iが= CCを<I ++)は、 " %D%D \ n " 、ANS [i]が1次回、ANS [I] .second)。
  リターン 0 ; 
}

 

おすすめ

転載: www.cnblogs.com/shxnb666/p/11291298.html