Pagini recente » Monitorul de evaluare | Diferente pentru info-oltenia-2019/individual/5-6 intre reviziile 2 si 3 | Monitorul de evaluare | Diferente pentru olimpici intre reviziile 180 si 90 | Cod sursa (job #2010542)
#include <algorithm>
#include <iostream>
#include <fstream>
#include <climits>
#include <cassert>
#include <bitset>
#include <vector>
#include <queue>
using namespace std;
ifstream in("cc.in");
ofstream out("cc.out");
const int NMAX = 2 * (100 + 1);
struct Edge{
int to;
int rev;
int flow;
int cap;
int cost;
};
struct Node{
int node;
int d;
bool operator> (Node other) const{
return d > other.d;
}
};
int n, src, dest;
int dist[1 + NMAX], distdij[1 + NMAX];
bitset<1 + NMAX> vis;
int prevnode[1 + NMAX], prevedge[1 + NMAX], pushflow[1 + NMAX];
vector < Edge > g[1 + NMAX];
void addedge(int from, int to, int cost){
Edge direct = {to, g[to].size(), 0, 1, cost};
Edge inverse = {from, g[from].size(), 0, 0, -cost};
g[from].push_back(direct);
g[to].push_back(inverse);
}
void bellmanford(){
queue < int > q;
fill(dist, dist + dest + 1, INT_MAX);
dist[src] = 0;
q.push(src);
while(!q.empty()){
int from = q.front();
vis[from] = 0;
q.pop();
for(int i = 0; i < g[from].size(); i++){
Edge &e = g[from][i];
if(e.flow < e.cap){
int to = e.to;
int newdist = dist[from] + e.cost;
if(newdist < dist[to]){
dist[to] = newdist;
if(vis[to] == 0){
q.push(to);
vis[to] = 1;
}
}
}
}
}
}
void dijkstra(){
vis = 0;
distdij[src] = 0;
pushflow[src] = INT_MAX;
priority_queue<Node, vector <Node>, greater<Node> > pq;
pq.push({src, distdij[src]});
while(!pq.empty()){
int from = pq.top().node;
pq.pop();
if(vis[from] == 0){
vis[from] = 1;
for(int i = 0; i < g[from].size(); i++){
Edge &e = g[from][i];
if(vis[e.to] == 0){
int to = e.to;
if(e.flow < e.cap){
int newdistdij = distdij[from] + e.cost + dist[from] - dist[to];
if(newdistdij < distdij[to]){
distdij[to] = newdistdij;
prevnode[to] = from;
prevedge[to] = i;
pushflow[to] = min(pushflow[from], e.cap - e.flow);
pq.push({to, distdij[to]});
}
}
}
}
}
}
}
void mincostflow(int &flow, int &flowcost) {
bellmanford();
//cout << "BF\n";
flow = flowcost = 0;
while(distdij[dest] < INT_MAX) {
fill(distdij + 1, distdij + dest + 1, INT_MAX);
dijkstra();
//cout << "DJ\n";
if(distdij[dest] < INT_MAX) {
//new level graph
for(int i = 1; i <= n; i++){
dist[i] += distdij[i];
}
//blocking flow
int deltaflow = pushflow[dest];
flow += deltaflow;
for(int to = dest; to != src; to = prevnode[to]) {
Edge &e = g[prevnode[to]][prevedge[to]];
e.flow += deltaflow;
g[to][e.rev].flow -= deltaflow;
flowcost += deltaflow * e.cost;
//cout << deltaflow << ' ' << e.cost << ' ' << flowcost << '\n';
}
}
}
}
int main()
{
in >> n;
src = 0;
dest = 2 * n + 1;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
int x;
in >> x;
addedge(i, j + n, x);
}
}
for(int i = 1; i <= n; i++)
addedge(src, i, 0);
for(int i = n + 1; i <= 2 * n; i++)
addedge(i, dest, 0);
int flow, flowcost;
mincostflow(flow, flowcost);
assert(0 < flowcost);
assert(flow == n);
out << flowcost << '\n';
in.close();
out.close();
return 0;
}