Pagini recente » Cod sursa (job #651146) | Cod sursa (job #2057171) | Cod sursa (job #1389866) | Monitorul de evaluare | Cod sursa (job #1800364)
#include <fstream>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
ifstream in("cc.in");
ofstream out("cc.out");
const int NMAX = 100;
const int INF = (1 << 30);
vector <int> G[NMAX+2], GP[NMAX+2];
int cost[NMAX+2][NMAX+2];
int tt[NMAX+2], C[NMAX+2][NMAX+2], F[NMAX+2][NMAX+2];
priority_queue< pair<int,int>, vector< pair<int,int> >, greater< pair<int,int> > > H;
bool viz[NMAX+2];
int d[NMAX+2], N;
bool DIJKSTRA( int st, int fn ) {
viz[st] = 1;
H.push( make_pair( 0, st ) );
while( !H.empty() ) {
pair<int,int> pp = H.top();
H.pop();
int nod = pp.second;
viz[nod] = 1;
for( int i = 0; i < (int)G[nod].size(); ++i ) {
int x = G[nod][i];
if( C[nod][x] - F[nod][x] <= 0 ) continue;
if( !viz[x] || d[nod] + cost[nod][x] < d[x] ) {
d[x] = d[nod] + cost[nod][x];
tt[ x ] = nod;
H.push( make_pair( d[x], x ) );
}
}
}
return viz[fn];
}
int MAX_FLOW_MIN_COST( int st, int fn ) {
int ans = 0;
while( DIJKSTRA(st, fn) ) {
for( int i = 0; i < (int)G[fn].size(); ++i ) {
int x = G[fn][i], special = x;
if( !viz[x] || F[x][fn] >= C[x][fn] ) continue;
int min_flow = C[x][fn] - F[x][fn];
for( ; x != st; x = tt[x] ) {
min_flow = min(min_flow, C[ tt[x] ][ x ] - F[ tt[x] ][ x ] );
}
x = special;
int tot_cost = cost[ x ][ fn ] * (C[x][fn] - F[x][fn]);
F[ x ][ fn ] += min_flow;
F[ fn ][ x ] -= min_flow;
for( ; x != st; x = tt[x] ) {
tot_cost += cost[ tt[x] ][ x ] * (C[ tt[x] ][ x ] - F[ tt[x] ][ x ]);
F[ tt[x] ][ x ] += min_flow;
F[ x ][ tt[x] ] -= min_flow;
}
///ans += tot_cost;
}
memset( viz, 0, sizeof(viz) );
memset( tt, 0, sizeof(tt) );
memset( d, 0, sizeof(d) );
}
for( int i = 0; i <= 2*N; ++i ) {
for( int j = 0; j < (int)G[i].size(); ++j ) {
int x = G[i][j];
ans += F[ i ][ x ]* cost[ i ][ x ];
}
}
return ans;
}
int main()
{
in >> N;
for( int i = 1; i <= N; ++i ) {
for( int j = 1; j <= N; ++j ) {
int x;
in >> x;
G[i].push_back( N+j );
G[ N+j ].push_back( i );
cost[i][N+j] = x;
C[i][N+j] = 1;
}
}
int START = 0, FINISH = 2*N+1;
for( int i = 1; i <= N; ++i ) {
G[START].push_back( i );
G[i].push_back( START );
cost[START][i] = 0;
C[START][i] = 1;
G[N+i].push_back( FINISH );
G[FINISH].push_back( N+i );
cost[ N+i ][ FINISH ] = 0;
C[ N+i ][FINISH] = 1;
}
out << MAX_FLOW_MIN_COST(START, FINISH);
return 0;
}