Index: SRM/399/1C.cpp ================================================================== --- SRM/399/1C.cpp +++ SRM/399/1C.cpp @@ -1,127 +1,188 @@ +#include +#include +#include #include #include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include using namespace std; +typedef long long LL; +typedef long double LD; +typedef complex CMP; - - - -static const int NV = 512; -typedef int flow; -typedef int vert; -typedef vert edge; -typedef vector edges; -typedef vector graph; -typedef flow flow_graph[NV][NV]; - -flow dinic_dfs( graph& G, flow_graph F, vert v, vert D, - int LV[], flow flow_in, int blocked[] ) +template +class IdGen { - flow flow_out = 0; - for(int i=0; i!=G[v].size(); ++i) - { - int u = G[v][i]; - if( LV[v]+1==LV[u] && F[v][u] ) - { - flow f = min(flow_in-flow_out, F[v][u]); - if( u==D || !blocked[u] && (f=dinic_dfs(G,F,u,D,LV,f,blocked)) ) - { - F[v][u] -= f; - F[u][v] += f; - flow_out += f; - if( flow_in == flow_out ) return flow_out; - } - } + map v2id_; + vector id2v_; +public: + int v2id(const T& v) { + if( !v2id_.count(v) ) { v2id_[v] = size(); id2v_.push_back(v); } + return v2id_[v]; } - blocked[v] = (flow_out==0); - return flow_out; -} + const T& id2v(int i) const { return id2v_[i]; } + int size() const { return id2v_.size(); } +}; -flow dinic( graph& G, flow_graph F, vert S, vert D ) +template +class MaxFlow { - for( flow total=0 ;; ) { - int LV[NV] = {0}; - vector Q(1, S); - for(int lv=1; !Q.empty(); ++lv) - { - vector Q2; - for(int i=0; i!=Q.size(); ++i) - { - edges& ne = G[Q[i]]; - for(int j=0; j!=ne.size(); ++j) - if( F[Q[i]][ne[j]] && !LV[ne[j]] && ne[j]!=S ) - LV[ne[j]]=lv, Q2.push_back(ne[j]); - } - Q.swap(Q2); - } + IdGen idgen; + vector G[NV]; + Flow F[NV][NV]; - if( !LV[D] ) - return total; - - int blocked[NV] = {}; - total += dinic_dfs( G, F, S, D, LV, 0x7fffffff, blocked ); +public: + void addEdge( Vert s_, Vert t_, Flow f ) + { + const int s = idgen.v2id(s_), t = idgen.v2id(t_); + G[s].push_back(t); + G[t].push_back(s); + F[s][t] = f; + F[t][s] = 0; } -} - - -struct DancingParty -{ - int maxDances(vector likes, int k) + Flow calc( Vert s_, Vert t_ ) { - int n = likes.size(); - #define SRC 0 - #define DST 1 - #define L(i) 2+n*0+i - #define R(i) 2+n*1+i - #define YL(i) 2+n*2+i - #define NL(i) 2+n*3+i - #define YR(i) 2+n*4+i - #define NR(i) 2+n*5+i + const int S = idgen.v2id(s_), D = idgen.v2id(t_); + for( Flow total=0 ;; ) { + // Do BFS and compute the level for each node. + int LV[NV] = {0}; + vector Q(1, S); + for(int lv=1; !Q.empty(); ++lv) { + vector Q2; + for(size_t i=0; i!=Q.size(); ++i) { + const vector& ne = G[Q[i]]; + for(size_t j=0; j!=ne.size(); ++j) + if( F[Q[i]][ne[j]] && !LV[ne[j]] && ne[j]!=S ) + LV[ne[j]]=lv, Q2.push_back(ne[j]); + } + Q.swap(Q2); + } + + // Destination is now unreachable. Done. + if( !LV[D] ) + return total; + + // Iterating DFS. + bool blocked[NV] = {}; + total += dinic_dfs( S, D, LV, 0x7fffffff, blocked ); + } + } - graph G(2+n*6); - - // Graph - for(int i=0; i0 ) { + F[v][u] -= f; + F[u][v] += f; + flow_out += f; + if( flow_in == flow_out ) return flow_out; + } + } } + blocked[v] = (flow_out==0); + return flow_out; + } +}; +class DancingParty { public: + int maxDances(vector likes, int k) + { + const int n = likes.size(); for(int M=1; M<=n; ++M) { - // Flow - flow_graph F = {}; - for(int i=0; i Vert; + auto_ptr< MaxFlow > mf(new MaxFlow); - F[R(i)][DST] = M; - F[YR(i)][R(i)] = M; - F[NR(i)][R(i)] = k; + for(int i=0; iaddEdge(Vert(0,0), Vert(1,i), M); // src L + mf->addEdge(Vert(1,i), Vert(2,i), M); // L YL + mf->addEdge(Vert(1,i), Vert(3,i), k); // L NL + mf->addEdge(Vert(4,i), Vert(6,i), M); // YR R + mf->addEdge(Vert(5,i), Vert(6,i), k); // NR R + mf->addEdge(Vert(6,i), Vert(7,0), M); // R dst for(int j=0; jaddEdge(Vert(2,i), Vert(4,j), 1); else - F[NL(i)][NR(j)] = 1; + mf->addEdge(Vert(3,i), Vert(5,j), 1); } - // Maxflow - if( dinic(G, F, SRC, DST) < M*n ) + if( mf->calc(Vert(0,0), Vert(7,0)) < M*n ) return M-1; } return n; } }; + +// BEGIN CUT HERE +#include +double start_time; string timer() + { ostringstream os; os << " (" << int((clock()-start_time)/CLOCKS_PER_SEC*1000) << " msec)"; return os.str(); } +template ostream& operator<<(ostream& os, const vector& v) + { os << "{ "; + for(typename vector::const_iterator it=v.begin(); it!=v.end(); ++it) + os << '\"' << *it << '\"' << (it+1==v.end() ? "" : ", "); os << " }"; return os; } +void verify_case(const int& Expected, const int& Received) { + bool ok = (Expected == Received); + if(ok) cerr << "PASSED" << timer() << endl; else { cerr << "FAILED" << timer() << endl; + cerr << "\to: \"" << Expected << '\"' << endl << "\tx: \"" << Received << '\"' << endl; } } +#define CASE(N) {cerr << "Test Case #" << N << "..." << flush; start_time=clock(); +#define END verify_case(_, DancingParty().maxDances(likes, k));} +int main(){ + +CASE(0) + string likes_[] = {"YYY", "YYY", "YYY"}; + vector likes(likes_, likes_+sizeof(likes_)/sizeof(*likes_)); + int k = 0; + int _ = 3; +END +CASE(1) + string likes_[] = {"YYY", "YYN", "YNY"}; + vector likes(likes_, likes_+sizeof(likes_)/sizeof(*likes_)); + int k = 0; + int _ = 2; +END +CASE(2) + string likes_[] = {"YN", "YN"}; + vector likes(likes_, likes_+sizeof(likes_)/sizeof(*likes_)); + int k = 0; + int _ = 0; +END +CASE(3) + string likes_[] = {"YN", "YN"}; + vector likes(likes_, likes_+sizeof(likes_)/sizeof(*likes_)); + int k = 1; + int _ = 1; +END +/* +CASE(4) + string likes_[] = ; + vector likes(likes_, likes_+sizeof(likes_)/sizeof(*likes_)); + int k = ; + int _ = ; +END +CASE(5) + string likes_[] = ; + vector likes(likes_, likes_+sizeof(likes_)/sizeof(*likes_)); + int k = ; + int _ = ; +END +*/ +} +// END CUT HERE Index: lib/graph/maxFlow.cpp ================================================================== --- lib/graph/maxFlow.cpp +++ lib/graph/maxFlow.cpp @@ -26,11 +26,11 @@ } const T& id2v(int i) const { return id2v_[i]; } int size() const { return id2v_.size(); } }; -template +template class MaxFlow { IdGen idgen; vector G[NV]; Flow F[NV][NV];