1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
| struct Edge { int v; ll c, w; }; vector<Edge> edge; vector< vector<int> > adj;
void init( int N, int M = 0 ) { edge.clear( ); if( M ) edge.reserve( M << 1 ); adj.assign( N + 1, { } ); }
void add_edge( int u, int v, ll c, ll w ) { if( u == v ) return; adj[u].push_back( edge.size( ) ); edge.push_back({ v, c, w }); adj[v].push_back( edge.size( ) ); edge.push_back({ u, 0, -w }); }
ll mxf[maxn]; ll dis[maxn]; int pre[maxn]; bool inq[maxn];
bool spfa( int S, int T, int N ) { for( int i = 0; i <= N; ++ i ) { dis[i] = inf, mxf[i] = 0; pre[i] = -1, inq[i] = false; } queue<int> q; q.push( S ); dis[S] = 0, mxf[S] = inf, inq[S] = true; while( !q.empty( ) ) { int u = q.front( ); q.pop( ); inq[u] = false; for( int id : adj[u] ) { auto [v, c, w] = edge[id]; if( c == 0 || dis[u] + w >= dis[v] ) continue; dis[v] = dis[u] + w; mxf[v] = min( mxf[u], c ); pre[v] = id; if( !inq[v] ) inq[v] = true, q.push( v ); } } return pre[T] != -1; }
pair<ll, ll> mincost_maxflow( int S, int T, int N, ll limit = inf ) { ll flow = 0, cost = 0; while( flow < limit && spfa( S, T, N ) ) { ll f = min( mxf[T], limit - flow ); flow += f; cost += f * dis[T]; for( int v = T; v != S; ) { int id = pre[v]; edge[id].c -= f; edge[id ^ 1].c += f; v = edge[id ^ 1].v; } } return { flow, cost }; }
ll a[55][55];
void solve( ) { int n = read( ); int S = 0, T = 2 * n + 1;
for( int i = 1; i <= n; ++ i ) { for( int j = 1; j <= n; ++ j ) { a[i][j] = read( ); } }
init( T ); for( int i = 1; i <= n; ++ i ) { for( int j = 1; j <= n; ++ j ) { add_edge( i, n + j, 1, a[i][j] ); } }
for( int i = 1; i <= n; ++ i ) { add_edge( S, i, 1, 0 ); add_edge( n + i, T, 1, 0 ); }
auto [flow1, mincost] = mincost_maxflow( S, T, T, n );
init( T ); for( int i = 1; i <= n; ++ i ) { for( int j = 1; j <= n; ++ j ) { add_edge( i, n + j, 1, -a[i][j] ); } }
for( int i = 1; i <= n; ++ i ) { add_edge( S, i, 1, 0 ); add_edge( n + i, T, 1, 0 ); }
auto [flow2, maxcost] = mincost_maxflow( S, T, T );
cout << mincost << "\n" << -maxcost << "\n"; }
|