Pagini recente » Cod sursa (job #2326121) | Cod sursa (job #1986694) | Cod sursa (job #3040094) | Cod sursa (job #2392993) | Cod sursa (job #610247)
Cod sursa(job #610247)
// Solutie:
//
// b - numarul membrilor organizatiei; b<=50.
// m - numarul drumurilor intre orase (muchiilor); m<=300
// n - numarul oraselor (arcelor); n<=50.
//
// T unitati de timp sunt suficiente, daca fluxul maxim in reteaua de transport
// ((v,t),(w,t+1)) pentru 0<=t<T unde {v,w} este muchie in graful oraselor,
// ((v,t),(v,t+1)) pentru 0<=t<T unde v este oras,
// ((0,0), (v,0)) unde v este un oras
// ((v,T), (0,T)) unde v este un oras
// s = (0,0), t = (0,T+1)
// este egal cu numarul membrilor organizatiei.
//
// Fluxul maxim este cel mult egal cu b.
// m' - numarul de arce ale retelei reziduale.
// Cu BFS, un drum de la s la t se gaseste in cel mult m' operatii.
// Fluxul maxim se poate calcula cu ford-fulkerson, in cel mult b*m' operatii.
//
// Topt <= Tmax=((n-1)+(b-1)) :
// {1,2},{2,3},...,{n-1,n}, pe fiecare din aceste muchii trece maxim 1 om, b oameni in n.
#include <fstream>
#include <algorithm>
#include <vector>
#include <queue>
int const maxn = 50;
int const maxm = 300;
int const maxb = 50;
int const minc = 1;
int const maxc = 10;
typedef std::pair<int, int> cendp_t;
class algola
{ // input
int a_n;
std::vector<int> a_b;
std::vector<std::vector<cendp_t> > a_adj;
int a_b_sum;
// flow
int a_n3;
int a_source; int a_sink;
std::vector<std::vector<int> > a_flow; int a_flow_value;
std::vector<std::vector<cendp_t> > a_adj3;
// max flow storage
std::vector<int> a_bfs_parent;
std::vector<int> a_fxy;
std::vector<int> a_bfs_queue;
// answer, status
int a_ans;
bool a_ok;
// helper (2) methods
void max_flow() throw ( );
void update_flow_network(int t);
void construct_flow_network();
// helper methods
bool write();
void solve();
bool read();
bool process();
public:
algola();
bool get_ok() const throw();
};
bool
algola::get_ok() const throw()
{ return a_ok; }
algola::algola()
: a_ok(process())
{ }
bool
algola::process()
{ bool ok; ok = read(); if(!ok) { return ok; }
solve(); ok = write(); return ok;
}
bool
algola::read()
{ // read input
bool ok;
std::ifstream is("algola.in");
ok = is.good(); if(!ok) { return ok; }
int n; int m; is >> n >> m;
ok = ((0<n)&&(maxn>=n)); if(!ok) { return ok; }
ok = ((0<m)&&(maxm>=m)); if(!ok) { return ok; }
std::vector<int> b(1+n);
int x; for(x=1; n>=x; ++x)
{ is >> b[x];
ok = (0<=b[x]); if(!ok) { return ok; }
}
int b_sum; b_sum = 0; for(x=1; n>=x; ++x) { b_sum += b[x]; }
ok = (b_sum<=maxb); if(!ok) { return ok; }
std::vector<std::vector<cendp_t> > adj(1+n);
int i; int y; int c;
for(i=0; m>i; ++i)
{ is >> x >> y >> c;
ok = ((1<=x)&&(x<=n)); if(!ok) { return ok; }
ok = ((1<=y)&&(y<=n)); if(!ok) { return ok; }
ok = ((minc<=c)&&(c<=maxc)); if(!ok) { return ok; }
adj[x].push_back(cendp_t(y, c));
adj[y].push_back(cendp_t(x, c));
}
ok = is.good(); if(!ok) { return ok; }
// no-throw
a_n = n;
a_b.swap(b);
a_adj.swap(adj);
a_b_sum = b_sum;
return ok;
}
void
algola::solve()
{ // solve
if(a_b_sum == a_b[1])
{ a_ans = 0; return; }
int t; t = 1;
construct_flow_network();
bool solved; solved = false;
do
{ max_flow();
if(a_flow_value == a_b_sum)
{ solved = true; }
else
{ update_flow_network(t); ++t; }
}
while(!solved);
a_ans = t;
}
bool
algola::write()
{ // write solution
std::ofstream os("algola.out");
os << a_ans << std::endl;
bool ok = os.good(); if(!ok) { return ok; }
os.close(); ok = os.good(); if(!ok) { return ok; }
return ok;
}
void
algola::construct_flow_network()
{ std::vector<int> & b (a_b);
int n; n = a_n; int b_sum; b_sum = a_b_sum;
int tmax; tmax = ((n-1)+(b_sum-1));
int tn; tn = (1+tmax) * (n+1); int x;
std::vector<std::vector<cendp_t> > adj3(tn);
for(x=1; n>=x; ++x)
{ if(0<b[x])
{ adj3[0*(n+1)+0].push_back(cendp_t(0*(n+1)+x, b[x]));
adj3[0*(n+1)+x].push_back(cendp_t(0*(n+1)+0, 0));
}
}
std::vector<std::vector<int> > flow(tn);
for(x=0; tn>x; ++x)
{ std::vector<int> zeroes(tn);
zeroes.swap(flow[x]);
}
std::vector<int> bfs_parent(tn);
std::vector<int> fxy(tn);
std::vector<int> bfs_queue(tn);
// no-throw
a_source = 0*(n+1) + 0;
a_flow.swap(flow);
a_flow_value = 0;
a_adj3.swap(adj3);
a_bfs_parent.swap(bfs_parent);
a_fxy.swap(fxy);
a_bfs_queue.swap(bfs_queue);
update_flow_network(0);
}
void
algola::update_flow_network(int t)
{ std::vector<std::vector<cendp_t> > & adj (a_adj);
int n; n = a_n; int b_sum; b_sum = a_b_sum;
std::vector<std::vector<cendp_t> > & adj3(a_adj3);
int t1; t1 = t; int t2; t2 = 1 + t1;
int x; int dx; int i; int y; int c;
for(x=1; n>=x; ++x)
{ adj3[t1*(n+1)+x].push_back(cendp_t(t2*(n+1)+x, b_sum));
adj3[t2*(n+1)+x].push_back(cendp_t(t1*(n+1)+x, 0));
dx = static_cast<int> (adj[x].size());
for(i=0; dx>i; ++i)
{ y = adj[x][i].first; c = adj[x][i].second;
adj3[t1*(n+1)+x].push_back(cendp_t(t2*(n+1)+y, c));
adj3[t2*(n+1)+y].push_back(cendp_t(t1*(n+1)+x, 0));
}
}
int oldsink; oldsink = t1*(n+1) + 1; int newsink = t2*(n+1) + 1;
std::vector<std::vector<int> > & flow(a_flow);
int flow_value; flow_value = a_flow_value;
flow[oldsink][newsink] = flow_value;
flow[newsink][oldsink] = -flow_value;
a_sink = newsink;
a_n3 = (1+t2)*(1+n);
}
void
algola::max_flow() throw ( )
{ std::vector<std::vector<cendp_t > > & adj (a_adj3);
int n; n = a_n3;
int source; source = a_source; int sink; sink = a_sink;
// Start from an initial flow.
std::vector<std::vector<int> > & flow = a_flow;
int & flow_value = a_flow_value;
// The Edmonds - Karp algorithm is a Ford-Fulkerson algorithm.
std::vector<int> & bfs_queue (a_bfs_queue);
int queue_in; int queue_out;
std::vector<int> & bfs_parent (a_bfs_parent);
std::vector<int> & fxy(a_fxy);
int y; int x; int dx; int i; int cxy; int new_flow;
do
{ queue_in = 0; queue_out = 0;
bfs_queue[queue_in] = source; ++ queue_in;
for(x=0; n>x; ++x) { bfs_parent[x] = -1; }
bfs_parent[source] = -2;
for(y=0; n>y; ++y) { fxy[y] = -1; }
while(queue_out < queue_in)
{ x = bfs_queue[queue_out]; ++ queue_out;
dx = static_cast<int>(adj[x].size());
for(i=0; dx>i; ++i)
{ y = adj[x][i].first; cxy = adj[x][i].second;
if((-1 == bfs_parent[y])&&(flow[x][y]<cxy))
{ bfs_parent[y] = x; fxy[y] = cxy - flow[x][y]; bfs_queue[queue_in] = y; ++queue_in; }
}
}
if(-1!=bfs_parent[sink])
{ new_flow = -1;
for(y=sink; source != y; y = bfs_parent[y])
{ if((-1==new_flow)||(new_flow>fxy[y])) { new_flow = fxy[y]; } }
for(y=sink; source != y; y = x)
{ x = bfs_parent[y]; flow[x][y] += new_flow; flow[y][x] -= new_flow; }
flow_value += new_flow;
}
else { new_flow = 0; }
}
while(0<new_flow);
}
bool
solve()
{ algola a;
return a.get_ok();
}
int
main()
{ int status;
bool ok;
try
{ ok = solve();
status = ( ok ? 0 : 1 );
}
catch ( ... )
{ status = 2; }
return status;
}