Differences From Artifact [b357fd2040b9449a]:
- File
SRM/399/1C.cpp
- 2011-02-23 09:21:16 - part of checkin [4fd800b3a8] on branch trunk - Copied from private svn repository. (user: kinaba) [annotate]
To Artifact [c3aca7366b0837d8]:
- File
SRM/399/1C.cpp
- 2012-05-20 14:30:32 - part of checkin [5919ac5f24] on branch trunk - 2048 (user: kinaba) [annotate]
> 1 #include <iostream>
> 2 #include <sstream>
> 3 #include <iomanip>
1 #include <vector> 4 #include <vector>
2 #include <string> 5 #include <string>
3 #include <iostream> | 6 #include <map>
> 7 #include <set>
> 8 #include <algorithm>
> 9 #include <numeric>
> 10 #include <iterator>
> 11 #include <memory>
> 12 #include <functional>
> 13 #include <complex>
> 14 #include <queue>
> 15 #include <stack>
4 #include <cstring> | 16 #include <cmath>
> 17 #include <cassert>
5 using namespace std; 18 using namespace std;
> 19 typedef long long LL;
> 20 typedef long double LD;
> 21 typedef complex<LD> CMP;
6 22
7 <
8 <
9 <
10 static const int NV = 512; <
11 typedef int flow; <
12 typedef int vert; <
13 typedef vert edge; <
14 typedef vector<edge> edges; <
15 typedef vector<edges> graph; <
16 typedef flow flow_graph[NV][NV]; <
17 <
18 flow dinic_dfs( graph& G, flow_graph F, vert v, vert D, <
19 int LV[], flow flow_in, int blocked[] ) <
> 23 template<typename T>
> 24 class IdGen
20 { 25 {
21 flow flow_out = 0; | 26 map<T, int> v2id_;
22 for(int i=0; i!=G[v].size(); ++i) | 27 vector<T> id2v_;
23 { <
> 28 public:
24 int u = G[v][i]; | 29 int v2id(const T& v) {
25 if( LV[v]+1==LV[u] && F[v][u] ) | 30 if( !v2id_.count(v) ) { v2id_[v] = size(); id2v_.push_back(v); }
26 { <
27 flow f = min(flow_in-flow_out, F[v][u]); <
28 if( u==D || !blocked[u] && (f=dinic_dfs(G,F,u,D,LV,f,blo <
29 { <
30 F[v][u] -= f; <
31 F[u][v] += f; <
32 flow_out += f; <
33 if( flow_in == flow_out ) return flow_out; <
34 } <
35 } <
> 31 return v2id_[v];
36 } 32 }
37 blocked[v] = (flow_out==0); | 33 const T& id2v(int i) const { return id2v_[i]; }
38 return flow_out; | 34 int size() const { return id2v_.size(); }
39 } | 35 };
40 36
41 flow dinic( graph& G, flow_graph F, vert S, vert D ) | 37 template<typename Vert, typename Flow, int NV=512>
> 38 class MaxFlow
42 { 39 {
43 for( flow total=0 ;; ) { | 40 IdGen<Vert> idgen;
44 int LV[NV] = {0}; <
45 vector<int> Q(1, S); <
46 for(int lv=1; !Q.empty(); ++lv) <
47 { <
48 vector<int> Q2; | 41 vector<int> G[NV];
49 for(int i=0; i!=Q.size(); ++i) <
50 { <
51 edges& ne = G[Q[i]]; <
52 for(int j=0; j!=ne.size(); ++j) <
53 if( F[Q[i]][ne[j]] && !LV[ne[j]] && ne[j <
54 LV[ne[j]]=lv, Q2.push_back(ne[j] <
55 } <
56 Q.swap(Q2); <
57 } <
> 42 Flow F[NV][NV];
58 43
59 if( !LV[D] ) | 44 public:
60 return total; | 45 void addEdge( Vert s_, Vert t_, Flow f )
61 | 46 {
62 int blocked[NV] = {}; | 47 const int s = idgen.v2id(s_), t = idgen.v2id(t_);
63 total += dinic_dfs( G, F, S, D, LV, 0x7fffffff, blocked ); | 48 G[s].push_back(t);
> 49 G[t].push_back(s);
> 50 F[s][t] = f;
> 51 F[t][s] = 0;
64 } 52 }
65 } <
66 53
67 <
68 <
69 struct DancingParty <
70 { <
71 int maxDances(vector<string> likes, int k) <
> 54 Flow calc( Vert s_, Vert t_ )
72 { 55 {
73 int n = likes.size(); | 56 const int S = idgen.v2id(s_), D = idgen.v2id(t_);
74 #define SRC 0 | 57 for( Flow total=0 ;; ) {
75 #define DST 1 | 58 // Do BFS and compute the level for each node.
76 #define L(i) 2+n*0+i | 59 int LV[NV] = {0};
77 #define R(i) 2+n*1+i | 60 vector<int> Q(1, S);
78 #define YL(i) 2+n*2+i | 61 for(int lv=1; !Q.empty(); ++lv) {
79 #define NL(i) 2+n*3+i | 62 vector<int> Q2;
80 #define YR(i) 2+n*4+i | 63 for(size_t i=0; i!=Q.size(); ++i) {
81 #define NR(i) 2+n*5+i | 64 const vector<int>& ne = G[Q[i]];
> 65 for(size_t j=0; j!=ne.size(); ++j)
> 66 if( F[Q[i]][ne[j]] && !LV[ne[j]]
> 67 LV[ne[j]]=lv, Q2.push_ba
> 68 }
> 69 Q.swap(Q2);
> 70 }
> 71
> 72 // Destination is now unreachable. Done.
> 73 if( !LV[D] )
> 74 return total;
> 75
> 76 // Iterating DFS.
> 77 bool blocked[NV] = {};
> 78 total += dinic_dfs( S, D, LV, 0x7fffffff, blocked );
> 79 }
> 80 }
82 81
83 graph G(2+n*6); | 82 private:
> 83 Flow dinic_dfs( int v, int D, int LV[], Flow flow_in, bool blocked[] )
84 | 84 {
85 // Graph <
86 for(int i=0; i<n; ++i) { | 85 Flow flow_out = 0;
87 G[SRC ].push_back(L(i)); G[L(i) ].push_back(SRC); | 86 for(size_t i=0; i!=G[v].size(); ++i) {
88 G[L(i)].push_back(YL(i)); G[YL(i)].push_back(L(i)); | 87 int u = G[v][i];
89 G[L(i)].push_back(NL(i)); G[NL(i)].push_back(L(i)); | 88 if( LV[v]+1==LV[u] && F[v][u] ) {
> 89 Flow f = min(flow_in-flow_out, F[v][u]);
> 90 if( u==D || !blocked[u] && (f=dinic_dfs(u,D,LV,f
> 91 F[v][u] -= f;
> 92 F[u][v] += f;
> 93 flow_out += f;
> 94 if( flow_in == flow_out ) return flow_ou
90 | 95 }
91 G[DST ].push_back(R(i)); G[R(i) ].push_back(DST); <
92 G[R(i)].push_back(YR(i)); G[YR(i)].push_back(R(i)); <
93 G[R(i)].push_back(NR(i)); G[NR(i)].push_back(R(i)); <
94 | 96 }
95 for(int j=0; j<n; ++j) <
96 if( likes[i][j] == 'Y' ) <
97 G[YL(i)].push_back(YR(j)), G[YR(j)].push <
98 else <
99 G[NL(i)].push_back(NR(j)), G[NR(j)].push <
100 } 97 }
> 98 blocked[v] = (flow_out==0);
> 99 return flow_out;
> 100 }
> 101 };
101 102
> 103 class DancingParty { public:
> 104 int maxDances(vector <string> likes, int k)
> 105 {
> 106 const int n = likes.size();
102 for(int M=1; M<=n; ++M) { 107 for(int M=1; M<=n; ++M) {
103 // Flow | 108 typedef pair<int,int> Vert;
104 flow_graph F = {}; | 109 auto_ptr< MaxFlow<Vert, int> > mf(new MaxFlow<Vert, int>
105 for(int i=0; i<n; ++i) { <
106 F[SRC][L(i)] = M; <
107 F[L(i)][YL(i)] = M; <
108 F[L(i)][NL(i)] = k; <
109 110
110 F[R(i)][DST] = M; | 111 for(int i=0; i<n; ++i) {
111 F[YR(i)][R(i)] = M; | 112 mf->addEdge(Vert(0,0), Vert(1,i), M); // src L
112 F[NR(i)][R(i)] = k; | 113 mf->addEdge(Vert(1,i), Vert(2,i), M); // L YL
> 114 mf->addEdge(Vert(1,i), Vert(3,i), k); // L NL
> 115 mf->addEdge(Vert(4,i), Vert(6,i), M); // YR R
> 116 mf->addEdge(Vert(5,i), Vert(6,i), k); // NR R
> 117 mf->addEdge(Vert(6,i), Vert(7,0), M); // R dst
113 118
114 for(int j=0; j<n; ++j) 119 for(int j=0; j<n; ++j)
115 if( likes[i][j] == 'Y' ) 120 if( likes[i][j] == 'Y' )
116 F[YL(i)][YR(j)] = 1; | 121 mf->addEdge(Vert(2,i), Vert(4,j)
117 else 122 else
118 F[NL(i)][NR(j)] = 1; | 123 mf->addEdge(Vert(3,i), Vert(5,j)
119 } 124 }
120 125
121 // Maxflow | 126 if( mf->calc(Vert(0,0), Vert(7,0)) < M*n )
122 if( dinic(G, F, SRC, DST) < M*n ) <
123 return M-1; 127 return M-1;
124 } 128 }
125 return n; 129 return n;
126 } 130 }
127 }; 131 };
> 132
> 133 // BEGIN CUT HERE
> 134 #include <ctime>
> 135 double start_time; string timer()
> 136 { ostringstream os; os << " (" << int((clock()-start_time)/CLOCKS_PER_SEC*1000)
> 137 template<typename T> ostream& operator<<(ostream& os, const vector<T>& v)
> 138 { os << "{ ";
> 139 for(typename vector<T>::const_iterator it=v.begin(); it!=v.end(); ++it)
> 140 os << '\"' << *it << '\"' << (it+1==v.end() ? "" : ", "); os << " }"; return
> 141 void verify_case(const int& Expected, const int& Received) {
> 142 bool ok = (Expected == Received);
> 143 if(ok) cerr << "PASSED" << timer() << endl; else { cerr << "FAILED" << timer()
> 144 cerr << "\to: \"" << Expected << '\"' << endl << "\tx: \"" << Received << '\"'
> 145 #define CASE(N) {cerr << "Test Case #" << N << "..." << flush; start_time=clock(
> 146 #define END verify_case(_, DancingParty().maxDances(likes, k));}
> 147 int main(){
> 148
> 149 CASE(0)
> 150 string likes_[] = {"YYY", "YYY", "YYY"};
> 151 vector <string> likes(likes_, likes_+sizeof(likes_)/sizeof(*likes_));
> 152 int k = 0;
> 153 int _ = 3;
> 154 END
> 155 CASE(1)
> 156 string likes_[] = {"YYY", "YYN", "YNY"};
> 157 vector <string> likes(likes_, likes_+sizeof(likes_)/sizeof(*likes_));
> 158 int k = 0;
> 159 int _ = 2;
> 160 END
> 161 CASE(2)
> 162 string likes_[] = {"YN", "YN"};
> 163 vector <string> likes(likes_, likes_+sizeof(likes_)/sizeof(*likes_));
> 164 int k = 0;
> 165 int _ = 0;
> 166 END
> 167 CASE(3)
> 168 string likes_[] = {"YN", "YN"};
> 169 vector <string> likes(likes_, likes_+sizeof(likes_)/sizeof(*likes_));
> 170 int k = 1;
> 171 int _ = 1;
> 172 END
> 173 /*
> 174 CASE(4)
> 175 string likes_[] = ;
> 176 vector <string> likes(likes_, likes_+sizeof(likes_)/sizeof(*likes_));
> 177 int k = ;
> 178 int _ = ;
> 179 END
> 180 CASE(5)
> 181 string likes_[] = ;
> 182 vector <string> likes(likes_, likes_+sizeof(likes_)/sizeof(*likes_));
> 183 int k = ;
> 184 int _ = ;
> 185 END
> 186 */
> 187 }
> 188 // END CUT HERE