Cod sursa(job #610247)

Utilizator mgntMarius B mgnt Data 26 august 2011 00:35:10
Problema Algola Scor 60
Compilator cpp Status done
Runda Arhiva de probleme Marime 6.89 kb
//  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;
}