/**
* Problem: Find the maximum flow in given graph
*
* Input:
* First line contains n and m: number of nodes and edges on graph
* From the second line to (m+1)'th line, each line contains u, v, c: an directed edge from u to v with capacity c
*
* Output:
* Only 1 line contains the maximum flow found on graph with source is vertex 1 and sink is vertex n
*
* Constraints:
* 1 <= n <= 10^5
* 1 <= m <= 10^6
* 1 <= c <= 10^9
* m <= n*(n-1)/2
* The given graph may contains both (u,v) and (v,u) with different capacities
* The given graph may contains duplicated edges (total capacity on that edge is the sum of individual capacities)
*
* Example:
* Input:
* 4 6
* 1 2 3
* 1 2 1
* 2 4 2
* 1 3 4
* 3 4 5
* 4 1 3
*
* Output:
* 6
*
**/
#include <bits/stdc++.h>
#define up(i,a,b) for (int i = (int)a; i <= (int)b; i++)
using namespace std;
const int maxn = 1e5 + 10 ;
const int MOD = 1e9 + 7 ;
const long long MODLL = 1000000000000000011LL;
// Dung luong flow toi da
int n,m,s,t;
struct EDGE{
int v, rev; //rev = chi so cua dinh u trong ma tran ke a[v]
long long capa;
long long flow;
} ;
vector< EDGE> a[ maxn] ;
// Do thi
long long excess[ maxn] ;
int height[ maxn] ;
bitset< maxn> active;
vector< int > B[ maxn] ;
int cnth[ maxn] ;
int highest;
int cnt_relabel, cnt_gap;
void activate( int u) {
if ( ! active[ u] && excess[ u] > 0 && height[ u] < n) {
active[ u] = true ;
B[ height[ u] ] .push_back ( u) ;
highest = max( highest, height[ u] ) ;
}
}
void make_gap( int k) {
up( u,1 ,n) if ( height[ u] >= k) {
B[ height[ u] ] .clear ( ) ;
-- cnth[ height[ u] ] ;
height[ u] = n;
++ cnth[ n] ;
}
++ cnt_gap;
// cout << "O(n)\n";
}
void push( int u, int i) {
EDGE& e = a[ u] [ i] ;
int v = e.v ;
long long delta = min( excess[ u] , e.capa - e.flow ) ;
EDGE& rev_e = a[ v] [ e.rev ] ;
e.flow + = delta;
rev_e.flow - = delta;
excess[ u] - = delta;
excess[ v] + = delta;
activate( v) ;
}
void relabel( int u) {
-- cnth[ height[ u] ] ;
height[ u] = n;
for ( EDGE e : a[ u] ) {
if ( e.capa - e.flow > 0 ) {
height[ u] = min( height[ u] , height[ e.v ] + 1 ) ;
}
}
++ cnth[ height[ u] ] ;
activate( u) ;
++ cnt_relabel;
// cout << "O(deg(u))\n";
}
void discharge( int u) {
for ( int i = 0 ; i < ( int ) a[ u] .size ( ) ; i++ ) {
EDGE e = a[ u] [ i] ;
int v = e.v ;
if ( e.capa - e.flow > 0 && height[ u] == height[ v] + 1 ) { //excess[u] > 0
push( u, i) ;
}
if ( excess[ u] == 0 ) return ;
}
if ( cnth[ height[ u] ] == 1 && cnt_relabel > 50 * cnt_gap) {
make_gap( height[ u] ) ;
} //Heuristic: choose good approximation
else relabel( u) ;
}
void findMincut( ) {
vector< pair< int , int > > min_cut;
long long sum = 0 ;
up( u,1 ,n) for ( EDGE e : a[ u] ) {
int v = e.v ;
long long capa = e.capa ;
if ( capa > 0 ) {
if ( height[ u] >= n && height[ v] < n) {
min_cut.push_back ( make_pair( u, v) ) ;
sum + = capa;
}
}
}
// cout << sum << "\n";
// cout << "\n";
// for (auto x : min_cut){
// cout << x.first << " " << x.second << "\n";
// }
}
void findMaxflow( ) {
excess[ s] = MODLL;
height[ s] = n;
cnth[ 0 ] = n- 1 ;
cnth[ n] = 1 ;
for ( int i = 0 ; i < ( int ) a[ s] .size ( ) ; i++ ) {
EDGE& e = a[ s] [ i] ;
if ( e.capa > 0 ) push( s, i) ;
}
while ( highest >= 0 ) {
while ( ! B[ highest] .empty ( ) ) {
int u = B[ highest] .back ( ) ;
B[ highest] .pop_back ( ) ;
active[ u] = false ;
if ( u == t) continue ;
discharge( u) ;
}
-- highest;
}
}
//----- INPUT AND BUILD GRAPH -----
map< pair< int , int > , long long > saved_edges;
map< pair< int , int > , bool > added;
void buildBiGraph( ) {
up( i,1 ,m) {
int u,v;
long long w;
cin >> u >> v >> w;
if ( u == v) continue ;
if ( u > v) swap( u, v) ;
saved_edges[ make_pair( u, v) ] + = w;
}
for ( auto e : saved_edges) {
int u = e.first .first ;
int v = e.first .second ;
long long w = e.second ;
a[ u] .push_back ( { v, int ( a[ v] .size ( ) ) , w, 0 } ) ;
a[ v] .push_back ( { u, int ( a[ u] .size ( ) ) - 1 , w, 0 } ) ;
}
}
void buildDiGraph( ) {
up( i,1 ,m) {
int u,v;
long long w;
cin >> u >> v >> w;
if ( u == v) continue ;
saved_edges[ make_pair( u, v) ] + = w;
}
for ( auto e : saved_edges) {
int u = e.first .first ;
int v = e.first .second ;
long long w = e.second ;
if ( ! added[ make_pair( u, v) ] ) {
added[ make_pair( u, v) ] = added[ make_pair( v, u) ] = true ;
a[ u] .push_back ( { v, int ( a[ v] .size ( ) ) , w, 0 } ) ;
a[ v] .push_back ( { u, int ( a[ u] .size ( ) ) - 1 , saved_edges[ make_pair( v, u) ] , 0 } ) ;
}
}
}
void find_flow_to_sink( ) ;
signed main( ) {
ios_base:: sync_with_stdio ( false ) ;
cin .tie ( 0 ) ;
#define Task "A"
if ( fopen ( Task".inp" , "r" ) ) {
freopen ( Task".inp" , "r" , stdin ) ;
freopen ( Task".out" , "w" , stdout ) ;
}
cin >> n >> m;
s = 1 , t = n;
buildDiGraph( ) ; //choose buildBiGraph() or buildDiGraph() to make graph bidirectional or not.
findMaxflow( ) ;
cout << excess[ t] ;
}
void find_flow_to_sink( ) {
long long sum2 = 0 ;
for ( EDGE& e : a[ t] ) {
int v = e.v ;
EDGE& rev_e = a[ v] [ e.rev ] ;
sum2 + = rev_e.flow ;
}
cout << sum2;
}
//Excess[t], sum(flow from v to t) with all v->t, or sum of capacity on Min-cut edges
//are all max flow we need to find
//Some nodes still have excess, but that's not problem to find max flow
LyoqCiAqIFByb2JsZW06IEZpbmQgdGhlIG1heGltdW0gZmxvdyBpbiBnaXZlbiBncmFwaAogKgogKiBJbnB1dDoKICogRmlyc3QgbGluZSBjb250YWlucyBuIGFuZCBtOiBudW1iZXIgb2Ygbm9kZXMgYW5kIGVkZ2VzIG9uIGdyYXBoCiAqIEZyb20gdGhlIHNlY29uZCBsaW5lIHRvIChtKzEpJ3RoIGxpbmUsIGVhY2ggbGluZSBjb250YWlucyB1LCB2LCBjOiBhbiBkaXJlY3RlZCBlZGdlIGZyb20gdSB0byB2IHdpdGggY2FwYWNpdHkgYwogKgogKiBPdXRwdXQ6CiAqIE9ubHkgMSBsaW5lIGNvbnRhaW5zIHRoZSBtYXhpbXVtIGZsb3cgZm91bmQgb24gZ3JhcGggd2l0aCBzb3VyY2UgaXMgdmVydGV4IDEgYW5kIHNpbmsgaXMgdmVydGV4IG4KICoKICogQ29uc3RyYWludHM6CiAqIDEgPD0gbiA8PSAxMF41CiAqIDEgPD0gbSA8PSAxMF42CiAqIDEgPD0gYyA8PSAxMF45CiAqIG0gPD0gbioobi0xKS8yCiAqIFRoZSBnaXZlbiBncmFwaCBtYXkgY29udGFpbnMgYm90aCAodSx2KSBhbmQgKHYsdSkgd2l0aCBkaWZmZXJlbnQgY2FwYWNpdGllcwogKiBUaGUgZ2l2ZW4gZ3JhcGggbWF5IGNvbnRhaW5zIGR1cGxpY2F0ZWQgZWRnZXMgKHRvdGFsIGNhcGFjaXR5IG9uIHRoYXQgZWRnZSBpcyB0aGUgc3VtIG9mIGluZGl2aWR1YWwgY2FwYWNpdGllcykKICoKICogRXhhbXBsZToKICogSW5wdXQ6CiAqIDQgNgogKiAxIDIgMwogKiAxIDIgMQogKiAyIDQgMgogKiAxIDMgNAogKiAzIDQgNQogKiA0IDEgMwogKgogKiBPdXRwdXQ6CiAqIDYKICoKKiovCgoKI2luY2x1ZGUgPGJpdHMvc3RkYysrLmg+CiNkZWZpbmUgdXAoaSxhLGIpIGZvciAoaW50IGkgPSAoaW50KWE7IGkgPD0gKGludCliOyBpKyspCnVzaW5nIG5hbWVzcGFjZSBzdGQ7Cgpjb25zdCBpbnQgbWF4biA9IDFlNSArIDEwOwpjb25zdCBpbnQgTU9EID0gMWU5ICsgNzsKY29uc3QgbG9uZyBsb25nIE1PRExMID0gMTAwMDAwMDAwMDAwMDAwMDAxMUxMOwovLyBEdW5nIGx1b25nIGZsb3cgdG9pIGRhCgoKaW50IG4sbSxzLHQ7CnN0cnVjdCBFREdFewogICAgaW50IHYsIHJldjsgLy9yZXYgPSBjaGkgc28gY3VhIGRpbmggdSB0cm9uZyBtYSB0cmFuIGtlIGFbdl0KICAgIGxvbmcgbG9uZyBjYXBhOwogICAgbG9uZyBsb25nIGZsb3c7Cn07CnZlY3RvcjxFREdFPiBhW21heG5dOwovLyBEbyB0aGkKCmxvbmcgbG9uZyBleGNlc3NbbWF4bl07CmludCBoZWlnaHRbbWF4bl07CmJpdHNldDxtYXhuPiBhY3RpdmU7CnZlY3RvcjxpbnQ+IEJbbWF4bl07CmludCBjbnRoW21heG5dOwoKaW50IGhpZ2hlc3Q7CgppbnQgY250X3JlbGFiZWwsIGNudF9nYXA7Cgp2b2lkIGFjdGl2YXRlKGludCB1KXsKICAgIGlmICghYWN0aXZlW3VdICYmIGV4Y2Vzc1t1XSA+IDAgJiYgaGVpZ2h0W3VdIDwgbil7CiAgICAgICAgYWN0aXZlW3VdID0gdHJ1ZTsKICAgICAgICBCW2hlaWdodFt1XV0ucHVzaF9iYWNrKHUpOwogICAgICAgIGhpZ2hlc3QgPSBtYXgoaGlnaGVzdCwgaGVpZ2h0W3VdKTsKICAgIH0KfQoKdm9pZCBtYWtlX2dhcChpbnQgayl7CiAgICB1cCh1LDEsbikgaWYgKGhlaWdodFt1XSA+PSBrKXsKICAgICAgICBCW2hlaWdodFt1XV0uY2xlYXIoKTsKICAgICAgICAtLWNudGhbaGVpZ2h0W3VdXTsKICAgICAgICBoZWlnaHRbdV0gPSBuOwogICAgICAgICsrY250aFtuXTsKICAgIH0KICAgICsrY250X2dhcDsKLy8gICAgY291dCA8PCAiTyhuKVxuIjsKfQoKdm9pZCBwdXNoKGludCB1LCBpbnQgaSl7CiAgICBFREdFJiBlID0gYVt1XVtpXTsKICAgIGludCB2ID0gZS52OwogICAgbG9uZyBsb25nIGRlbHRhID0gbWluKGV4Y2Vzc1t1XSwgZS5jYXBhIC0gZS5mbG93KTsKCiAgICBFREdFJiByZXZfZSA9IGFbdl1bZS5yZXZdOwoKICAgIGUuZmxvdyArPSBkZWx0YTsKICAgIHJldl9lLmZsb3cgLT0gZGVsdGE7CiAgICBleGNlc3NbdV0gLT0gZGVsdGE7CiAgICBleGNlc3Nbdl0gKz0gZGVsdGE7CiAgICBhY3RpdmF0ZSh2KTsKfQoKdm9pZCByZWxhYmVsKGludCB1KXsKICAgIC0tY250aFtoZWlnaHRbdV1dOwogICAgaGVpZ2h0W3VdID0gbjsKICAgIGZvciAoRURHRSBlIDogYVt1XSl7CiAgICAgICAgaWYgKGUuY2FwYSAtIGUuZmxvdyA+IDApewogICAgICAgICAgICBoZWlnaHRbdV0gPSBtaW4oaGVpZ2h0W3VdLCBoZWlnaHRbZS52XSArIDEpOwogICAgICAgIH0KICAgIH0KICAgICsrY250aFtoZWlnaHRbdV1dOwogICAgYWN0aXZhdGUodSk7CiAgICArK2NudF9yZWxhYmVsOwovLyAgICBjb3V0IDw8ICJPKGRlZyh1KSlcbiI7Cn0KCnZvaWQgZGlzY2hhcmdlKGludCB1KXsKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgKGludClhW3VdLnNpemUoKTsgaSsrKXsKICAgICAgICBFREdFIGUgPSBhW3VdW2ldOwogICAgICAgIGludCB2ID0gZS52OwogICAgICAgIGlmIChlLmNhcGEgLSBlLmZsb3cgPiAwICYmIGhlaWdodFt1XSA9PSBoZWlnaHRbdl0gKyAxKXsgLy9leGNlc3NbdV0gPiAwCiAgICAgICAgICAgIHB1c2godSwgaSk7CiAgICAgICAgfQogICAgICAgIGlmIChleGNlc3NbdV0gPT0gMCkgcmV0dXJuOwogICAgfQoKICAgIGlmIChjbnRoW2hlaWdodFt1XV0gPT0gMSAmJiBjbnRfcmVsYWJlbCA+IDUwKmNudF9nYXApewogICAgICAgIG1ha2VfZ2FwKGhlaWdodFt1XSk7CiAgICB9IC8vSGV1cmlzdGljOiBjaG9vc2UgZ29vZCBhcHByb3hpbWF0aW9uCiAgICBlbHNlIHJlbGFiZWwodSk7Cn0KCnZvaWQgZmluZE1pbmN1dCgpewogICAgdmVjdG9yPHBhaXI8aW50LCBpbnQ+ID4gbWluX2N1dDsKICAgIGxvbmcgbG9uZyBzdW0gPSAwOwogICAgdXAodSwxLG4pIGZvciAoRURHRSBlIDogYVt1XSl7CiAgICAgICAgaW50IHYgPSBlLnY7CiAgICAgICAgbG9uZyBsb25nIGNhcGEgPSBlLmNhcGE7CiAgICAgICAgaWYgKGNhcGEgPiAwKXsKICAgICAgICAgICAgaWYgKGhlaWdodFt1XSA+PSBuICYmIGhlaWdodFt2XSA8IG4pewogICAgICAgICAgICAgICAgbWluX2N1dC5wdXNoX2JhY2sobWFrZV9wYWlyKHUsIHYpKTsKICAgICAgICAgICAgICAgIHN1bSArPSBjYXBhOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKLy8gICAgY291dCA8PCBzdW0gPDwgIlxuIjsKLy8gICAgY291dCA8PCAiXG4iOwovLyAgICBmb3IgKGF1dG8geCA6IG1pbl9jdXQpewovLyAgICAgICAgY291dCA8PCB4LmZpcnN0IDw8ICIgIiA8PCB4LnNlY29uZCA8PCAiXG4iOwovLyAgICB9Cn0KCnZvaWQgZmluZE1heGZsb3coKXsKICAgIGV4Y2Vzc1tzXSA9IE1PRExMOwogICAgaGVpZ2h0W3NdID0gbjsKICAgIGNudGhbMF0gPSBuLTE7CiAgICBjbnRoW25dID0gMTsKCiAgICBmb3IgKGludCBpID0gMDsgaSA8IChpbnQpYVtzXS5zaXplKCk7IGkrKyl7CiAgICAgICAgRURHRSYgZSA9IGFbc11baV07CiAgICAgICAgaWYgKGUuY2FwYSA+IDApIHB1c2gocywgaSk7CiAgICB9CgogICAgd2hpbGUgKGhpZ2hlc3QgPj0gMCl7CiAgICAgICAgd2hpbGUgKCFCW2hpZ2hlc3RdLmVtcHR5KCkpewogICAgICAgICAgICBpbnQgdSA9IEJbaGlnaGVzdF0uYmFjaygpOwogICAgICAgICAgICBCW2hpZ2hlc3RdLnBvcF9iYWNrKCk7CiAgICAgICAgICAgIGFjdGl2ZVt1XSA9IGZhbHNlOwogICAgICAgICAgICBpZiAodSA9PSB0KSBjb250aW51ZTsKICAgICAgICAgICAgZGlzY2hhcmdlKHUpOwogICAgICAgIH0KICAgICAgICAtLWhpZ2hlc3Q7CiAgICB9Cn0KCgoKCgovLy0tLS0tIElOUFVUIEFORCBCVUlMRCBHUkFQSCAtLS0tLQptYXA8cGFpcjxpbnQsIGludD4sIGxvbmcgbG9uZz4gc2F2ZWRfZWRnZXM7Cm1hcDxwYWlyPGludCwgaW50PiwgYm9vbD4gYWRkZWQ7Cgp2b2lkIGJ1aWxkQmlHcmFwaCgpewogICAgdXAoaSwxLG0pewogICAgICAgIGludCB1LHY7CiAgICAgICAgbG9uZyBsb25nIHc7CiAgICAgICAgY2luID4+IHUgPj4gdiA+PiB3OwogICAgICAgIGlmICh1ID09IHYpIGNvbnRpbnVlOwogICAgICAgIGlmICh1ID4gdikgc3dhcCh1LCB2KTsKICAgICAgICBzYXZlZF9lZGdlc1ttYWtlX3BhaXIodSwgdildICs9IHc7CiAgICB9CgogICAgZm9yIChhdXRvIGUgOiBzYXZlZF9lZGdlcyl7CiAgICAgICAgaW50IHUgPSBlLmZpcnN0LmZpcnN0OwogICAgICAgIGludCB2ID0gZS5maXJzdC5zZWNvbmQ7CiAgICAgICAgbG9uZyBsb25nIHcgPSBlLnNlY29uZDsKCiAgICAgICAgYVt1XS5wdXNoX2JhY2soe3YsIGludChhW3ZdLnNpemUoKSksIHcsIDB9KTsKICAgICAgICBhW3ZdLnB1c2hfYmFjayh7dSwgaW50KGFbdV0uc2l6ZSgpKS0xLCB3LCAwfSk7CiAgICB9Cn0KCnZvaWQgYnVpbGREaUdyYXBoKCl7CiAgICB1cChpLDEsbSl7CiAgICAgICAgaW50IHUsdjsKICAgICAgICBsb25nIGxvbmcgdzsKICAgICAgICBjaW4gPj4gdSA+PiB2ID4+IHc7CiAgICAgICAgaWYgKHUgPT0gdikgY29udGludWU7CiAgICAgICAgc2F2ZWRfZWRnZXNbbWFrZV9wYWlyKHUsIHYpXSArPSB3OwogICAgfQoKICAgIGZvciAoYXV0byBlIDogc2F2ZWRfZWRnZXMpewogICAgICAgIGludCB1ID0gZS5maXJzdC5maXJzdDsKICAgICAgICBpbnQgdiA9IGUuZmlyc3Quc2Vjb25kOwogICAgICAgIGxvbmcgbG9uZyB3ID0gZS5zZWNvbmQ7CgogICAgICAgIGlmICghYWRkZWRbbWFrZV9wYWlyKHUsIHYpXSl7CiAgICAgICAgICAgIGFkZGVkW21ha2VfcGFpcih1LCB2KV0gPSBhZGRlZFttYWtlX3BhaXIodiwgdSldID0gdHJ1ZTsKICAgICAgICAgICAgYVt1XS5wdXNoX2JhY2soe3YsIGludChhW3ZdLnNpemUoKSksIHcsIDB9KTsKICAgICAgICAgICAgYVt2XS5wdXNoX2JhY2soe3UsIGludChhW3VdLnNpemUoKSktMSwgc2F2ZWRfZWRnZXNbbWFrZV9wYWlyKHYsIHUpXSwgMH0pOwogICAgICAgIH0KICAgIH0KfQoKdm9pZCBmaW5kX2Zsb3dfdG9fc2luaygpOwoKc2lnbmVkIG1haW4oKXsKICAgIGlvc19iYXNlOjpzeW5jX3dpdGhfc3RkaW8oZmFsc2UpOwogICAgY2luLnRpZSgwKTsKICAgICNkZWZpbmUgVGFzayAiQSIKICAgIGlmIChmb3BlbihUYXNrIi5pbnAiLCAiciIpKXsKICAgICAgICBmcmVvcGVuKFRhc2siLmlucCIsICJyIiwgc3RkaW4pOwogICAgICAgIGZyZW9wZW4oVGFzayIub3V0IiwgInciLCBzdGRvdXQpOwogICAgfQoKICAgIGNpbiA+PiBuID4+IG07CiAgICBzID0gMSwgdCA9IG47CgogICAgYnVpbGREaUdyYXBoKCk7IC8vY2hvb3NlIGJ1aWxkQmlHcmFwaCgpIG9yIGJ1aWxkRGlHcmFwaCgpIHRvIG1ha2UgZ3JhcGggYmlkaXJlY3Rpb25hbCBvciBub3QuCiAgICBmaW5kTWF4ZmxvdygpOwogICAgY291dCA8PCBleGNlc3NbdF07Cn0KCgoKdm9pZCBmaW5kX2Zsb3dfdG9fc2luaygpewogICAgbG9uZyBsb25nIHN1bTIgPSAwOwogICAgZm9yIChFREdFJiBlIDogYVt0XSl7CiAgICAgICAgaW50IHYgPSBlLnY7CiAgICAgICAgRURHRSYgcmV2X2UgPSBhW3ZdW2UucmV2XTsKICAgICAgICBzdW0yICs9IHJldl9lLmZsb3c7CiAgICB9CiAgICBjb3V0IDw8IHN1bTI7Cn0KCi8vRXhjZXNzW3RdLCBzdW0oZmxvdyBmcm9tIHYgdG8gdCkgd2l0aCBhbGwgdi0+dCwgb3Igc3VtIG9mIGNhcGFjaXR5IG9uIE1pbi1jdXQgZWRnZXMKLy9hcmUgYWxsIG1heCBmbG93IHdlIG5lZWQgdG8gZmluZAoKLy9Tb21lIG5vZGVzIHN0aWxsIGhhdmUgZXhjZXNzLCBidXQgdGhhdCdzIG5vdCBwcm9ibGVtIHRvIGZpbmQgbWF4IGZsb3cK