552e57677b 2013-06-14 kinaba: #include <iostream> 552e57677b 2013-06-14 kinaba: #include <sstream> 552e57677b 2013-06-14 kinaba: #include <iomanip> 552e57677b 2013-06-14 kinaba: #include <vector> 552e57677b 2013-06-14 kinaba: #include <string> 552e57677b 2013-06-14 kinaba: #include <map> 552e57677b 2013-06-14 kinaba: #include <set> 552e57677b 2013-06-14 kinaba: #include <algorithm> 552e57677b 2013-06-14 kinaba: #include <numeric> 552e57677b 2013-06-14 kinaba: #include <iterator> 552e57677b 2013-06-14 kinaba: #include <functional> 552e57677b 2013-06-14 kinaba: #include <complex> 552e57677b 2013-06-14 kinaba: #include <queue> 552e57677b 2013-06-14 kinaba: #include <stack> 552e57677b 2013-06-14 kinaba: #include <cmath> 552e57677b 2013-06-14 kinaba: #include <cassert> 552e57677b 2013-06-14 kinaba: using namespace std; 552e57677b 2013-06-14 kinaba: typedef long long LL; 552e57677b 2013-06-14 kinaba: typedef long double LD; 552e57677b 2013-06-14 kinaba: typedef complex<double> CMP; 552e57677b 2013-06-14 kinaba: 552e57677b 2013-06-14 kinaba: const int dy[] = {-1,+1,0,0}; 552e57677b 2013-06-14 kinaba: const int dx[] = {0,0,-1,+1}; 552e57677b 2013-06-14 kinaba: 552e57677b 2013-06-14 kinaba: template<typename T> 552e57677b 2013-06-14 kinaba: class IdGen 552e57677b 2013-06-14 kinaba: { 552e57677b 2013-06-14 kinaba: map<T, int> v2id_; 552e57677b 2013-06-14 kinaba: vector<T> id2v_; 552e57677b 2013-06-14 kinaba: public: 552e57677b 2013-06-14 kinaba: int v2id(const T& v) { 552e57677b 2013-06-14 kinaba: if( !v2id_.count(v) ) { v2id_[v] = size(); id2v_.push_back(v); } 552e57677b 2013-06-14 kinaba: return v2id_[v]; 552e57677b 2013-06-14 kinaba: } 552e57677b 2013-06-14 kinaba: const T& id2v(int i) const { return id2v_[i]; } 552e57677b 2013-06-14 kinaba: int size() const { return id2v_.size(); } 552e57677b 2013-06-14 kinaba: }; 552e57677b 2013-06-14 kinaba: 552e57677b 2013-06-14 kinaba: template<typename Vert, typename Flow, int NV=2048> 552e57677b 2013-06-14 kinaba: class MaxFlow 552e57677b 2013-06-14 kinaba: { 552e57677b 2013-06-14 kinaba: IdGen<Vert> idgen; 552e57677b 2013-06-14 kinaba: vector<int> G[NV]; 552e57677b 2013-06-14 kinaba: Flow F[NV][NV]; 552e57677b 2013-06-14 kinaba: 552e57677b 2013-06-14 kinaba: public: 552e57677b 2013-06-14 kinaba: void addEdge( Vert s_, Vert t_, Flow f ) 552e57677b 2013-06-14 kinaba: { 552e57677b 2013-06-14 kinaba: const int s = idgen.v2id(s_), t = idgen.v2id(t_); 552e57677b 2013-06-14 kinaba: G[s].push_back(t); 552e57677b 2013-06-14 kinaba: G[t].push_back(s); 552e57677b 2013-06-14 kinaba: F[s][t] = f; 552e57677b 2013-06-14 kinaba: F[t][s] = 0; 552e57677b 2013-06-14 kinaba: } 552e57677b 2013-06-14 kinaba: 552e57677b 2013-06-14 kinaba: Flow calc( Vert s_, Vert t_ ) 552e57677b 2013-06-14 kinaba: { 552e57677b 2013-06-14 kinaba: const int S = idgen.v2id(s_), D = idgen.v2id(t_); 552e57677b 2013-06-14 kinaba: for( Flow total=0 ;; ) { 552e57677b 2013-06-14 kinaba: // Do BFS and compute the level for each node. 552e57677b 2013-06-14 kinaba: int LV[NV] = {0}; 552e57677b 2013-06-14 kinaba: vector<int> Q(1, S); 552e57677b 2013-06-14 kinaba: for(int lv=1; !Q.empty(); ++lv) { 552e57677b 2013-06-14 kinaba: vector<int> Q2; 552e57677b 2013-06-14 kinaba: for(size_t i=0; i!=Q.size(); ++i) { 552e57677b 2013-06-14 kinaba: const vector<int>& ne = G[Q[i]]; 552e57677b 2013-06-14 kinaba: for(size_t j=0; j!=ne.size(); ++j) 552e57677b 2013-06-14 kinaba: if( F[Q[i]][ne[j]] && !LV[ne[j]] && ne[j]!=S ) 552e57677b 2013-06-14 kinaba: LV[ne[j]]=lv, Q2.push_back(ne[j]); 552e57677b 2013-06-14 kinaba: } 552e57677b 2013-06-14 kinaba: Q.swap(Q2); 552e57677b 2013-06-14 kinaba: } 552e57677b 2013-06-14 kinaba: 552e57677b 2013-06-14 kinaba: // Destination is now unreachable. Done. 552e57677b 2013-06-14 kinaba: if( !LV[D] ) 552e57677b 2013-06-14 kinaba: return total; 552e57677b 2013-06-14 kinaba: 552e57677b 2013-06-14 kinaba: // Iterating DFS. 552e57677b 2013-06-14 kinaba: bool blocked[NV] = {}; 552e57677b 2013-06-14 kinaba: total += dinic_dfs( S, D, LV, 0x7fffffff, blocked ); 552e57677b 2013-06-14 kinaba: } 552e57677b 2013-06-14 kinaba: } 552e57677b 2013-06-14 kinaba: 552e57677b 2013-06-14 kinaba: private: 552e57677b 2013-06-14 kinaba: Flow dinic_dfs( int v, int D, int LV[], Flow flow_in, bool blocked[] ) 552e57677b 2013-06-14 kinaba: { 552e57677b 2013-06-14 kinaba: Flow flow_out = 0; 552e57677b 2013-06-14 kinaba: for(size_t i=0; i!=G[v].size(); ++i) { 552e57677b 2013-06-14 kinaba: int u = G[v][i]; 552e57677b 2013-06-14 kinaba: if( LV[v]+1==LV[u] && F[v][u] ) { 552e57677b 2013-06-14 kinaba: Flow f = min(flow_in-flow_out, F[v][u]); 552e57677b 2013-06-14 kinaba: if( u==D || !blocked[u] && (f=dinic_dfs(u,D,LV,f,blocked))>0 ) { 552e57677b 2013-06-14 kinaba: F[v][u] -= f; 552e57677b 2013-06-14 kinaba: F[u][v] += f; 552e57677b 2013-06-14 kinaba: flow_out += f; 552e57677b 2013-06-14 kinaba: if( flow_in == flow_out ) return flow_out; 552e57677b 2013-06-14 kinaba: } 552e57677b 2013-06-14 kinaba: } 552e57677b 2013-06-14 kinaba: } 552e57677b 2013-06-14 kinaba: blocked[v] = (flow_out==0); 552e57677b 2013-06-14 kinaba: return flow_out; 552e57677b 2013-06-14 kinaba: } 552e57677b 2013-06-14 kinaba: }; 552e57677b 2013-06-14 kinaba: 552e57677b 2013-06-14 kinaba: class Block3Checkers { public: 552e57677b 2013-06-14 kinaba: int blockThem(vector <string> board) 552e57677b 2013-06-14 kinaba: { 552e57677b 2013-06-14 kinaba: int H = board.size(); 552e57677b 2013-06-14 kinaba: int W = board[0].size(); 552e57677b 2013-06-14 kinaba: for(int y=0; y<H; ++y) 552e57677b 2013-06-14 kinaba: for(int x=0; x<W; ++x) 552e57677b 2013-06-14 kinaba: if(board[y][x] == 'A') { 552e57677b 2013-06-14 kinaba: for(int d=0; d<4; ++d) { 552e57677b 2013-06-14 kinaba: int xx = x+dx[d]; 552e57677b 2013-06-14 kinaba: int yy = y+dy[d]; 552e57677b 2013-06-14 kinaba: if(0<=xx&&xx<W&&0<=yy&&yy<H&&board[yy][xx]=='A') 552e57677b 2013-06-14 kinaba: return 100; 552e57677b 2013-06-14 kinaba: } 552e57677b 2013-06-14 kinaba: } 552e57677b 2013-06-14 kinaba: 552e57677b 2013-06-14 kinaba: vector<pair<int,int> > ps, as; 552e57677b 2013-06-14 kinaba: for(int y=0; y<H; ++y) 552e57677b 2013-06-14 kinaba: for(int x=0; x<W; ++x) 552e57677b 2013-06-14 kinaba: if(board[y][x]=='.') 552e57677b 2013-06-14 kinaba: ps.push_back(make_pair(y,x)); 552e57677b 2013-06-14 kinaba: else if(board[y][x]=='A') 552e57677b 2013-06-14 kinaba: as.push_back(make_pair(y,x)); 552e57677b 2013-06-14 kinaba: 552e57677b 2013-06-14 kinaba: vector<vector<int> > rf; 552e57677b 2013-06-14 kinaba: if(ok(board,as,rf)) 552e57677b 2013-06-14 kinaba: return 0; 552e57677b 2013-06-14 kinaba: for(int i=0; i<ps.size(); ++i) { 552e57677b 2013-06-14 kinaba: int y = ps[i].first; 552e57677b 2013-06-14 kinaba: int x = ps[i].second; 552e57677b 2013-06-14 kinaba: board[y][x] = 'N'; 552e57677b 2013-06-14 kinaba: if(ok(board,as,rf)) 552e57677b 2013-06-14 kinaba: return 1; 552e57677b 2013-06-14 kinaba: board[y][x] = '.'; 552e57677b 2013-06-14 kinaba: } 552e57677b 2013-06-14 kinaba: int best = 6; 552e57677b 2013-06-14 kinaba: for(int i=0; i<ps.size(); ++i) 552e57677b 2013-06-14 kinaba: for(int k=i+1; k<ps.size(); ++k) { 552e57677b 2013-06-14 kinaba: int y1 = ps[i].first; 552e57677b 2013-06-14 kinaba: int x1 = ps[i].second; 552e57677b 2013-06-14 kinaba: int y2 = ps[k].first; 552e57677b 2013-06-14 kinaba: int x2 = ps[k].second; 552e57677b 2013-06-14 kinaba: board[y1][x1] = 'N'; 552e57677b 2013-06-14 kinaba: board[y2][x2] = 'N'; 552e57677b 2013-06-14 kinaba: if(ok(board,as,rf)) 552e57677b 2013-06-14 kinaba: return 2; 552e57677b 2013-06-14 kinaba: if(rf[as[0].first][as[0].first] == (1<<0)) 552e57677b 2013-06-14 kinaba: best = min(best, 2+split(board, as[1], as[2])); 552e57677b 2013-06-14 kinaba: if(rf[as[1].first][as[1].first] == (1<<1)) 552e57677b 2013-06-14 kinaba: best = min(best, 2+split(board, as[2], as[0])); 552e57677b 2013-06-14 kinaba: if(rf[as[2].first][as[2].first] == (1<<2)) 552e57677b 2013-06-14 kinaba: best = min(best, 2+split(board, as[0], as[1])); 552e57677b 2013-06-14 kinaba: board[y1][x1] = '.'; 552e57677b 2013-06-14 kinaba: board[y2][x2] = '.'; 552e57677b 2013-06-14 kinaba: } 552e57677b 2013-06-14 kinaba: 552e57677b 2013-06-14 kinaba: return best; 552e57677b 2013-06-14 kinaba: } 552e57677b 2013-06-14 kinaba: 552e57677b 2013-06-14 kinaba: bool ok(const vector<string>& B, vector<pair<int,int> >& as, vector<vector<int> >& rf) 552e57677b 2013-06-14 kinaba: { 552e57677b 2013-06-14 kinaba: int H = B.size(); 552e57677b 2013-06-14 kinaba: int W = B[0].size(); 552e57677b 2013-06-14 kinaba: rf.assign(H, vector<int>(W, 0)); 552e57677b 2013-06-14 kinaba: for(int i=0; i<as.size(); ++i) 552e57677b 2013-06-14 kinaba: { 552e57677b 2013-06-14 kinaba: int ay = as[i].first; 552e57677b 2013-06-14 kinaba: int ax = as[i].second; 552e57677b 2013-06-14 kinaba: rf[ay][ax] |= (1<<i); 552e57677b 2013-06-14 kinaba: queue<pair<int,int> > q; 552e57677b 2013-06-14 kinaba: q.push(as[i]); 552e57677b 2013-06-14 kinaba: while(!q.empty()) { 552e57677b 2013-06-14 kinaba: int y = q.front().first; 552e57677b 2013-06-14 kinaba: int x = q.front().second; 552e57677b 2013-06-14 kinaba: q.pop(); 552e57677b 2013-06-14 kinaba: for(int d=0; d<4; ++d) { 552e57677b 2013-06-14 kinaba: int yy = y+dy[d]; 552e57677b 2013-06-14 kinaba: int xx = x+dx[d]; 552e57677b 2013-06-14 kinaba: if(0<=yy&&yy<H&&0<=xx&&xx<W&&B[y][x]!='N'&&!(rf[yy][xx]&(1<<i))) { 552e57677b 2013-06-14 kinaba: rf[yy][xx] |= 1<<i; 552e57677b 2013-06-14 kinaba: q.push(make_pair(yy,xx)); 552e57677b 2013-06-14 kinaba: } 552e57677b 2013-06-14 kinaba: } 552e57677b 2013-06-14 kinaba: } 552e57677b 2013-06-14 kinaba: } 552e57677b 2013-06-14 kinaba: for(int i=0; i<as.size(); ++i) 552e57677b 2013-06-14 kinaba: if(rf[as[i].first][as[i].second] != (1<<i)) 552e57677b 2013-06-14 kinaba: return false; 552e57677b 2013-06-14 kinaba: return true; 552e57677b 2013-06-14 kinaba: } 552e57677b 2013-06-14 kinaba: 552e57677b 2013-06-14 kinaba: int split(const vector<string>& B, pair<int,int> S, pair<int,int> D) 552e57677b 2013-06-14 kinaba: { 552e57677b 2013-06-14 kinaba: int OUT = 0, IN = 1; 552e57677b 2013-06-14 kinaba: typedef pair<int, pair<int,int> > Vert; 552e57677b 2013-06-14 kinaba: MaxFlow<Vert, int>* mf = new MaxFlow<Vert,int>; 552e57677b 2013-06-14 kinaba: int H = B.size(); 552e57677b 2013-06-14 kinaba: int W = B[0].size(); 552e57677b 2013-06-14 kinaba: for(int y=0; y<H; ++y) 552e57677b 2013-06-14 kinaba: for(int x=0; x<W; ++x) 552e57677b 2013-06-14 kinaba: if(B[y][x] != 'N') { 552e57677b 2013-06-14 kinaba: pair<int,int> p(y,x); 552e57677b 2013-06-14 kinaba: for(int d=0; d<4; ++d) { 552e57677b 2013-06-14 kinaba: int xx = x+dx[d]; 552e57677b 2013-06-14 kinaba: int yy = y+dy[d]; 552e57677b 2013-06-14 kinaba: if(0<=xx&&xx<W&&0<=yy&&yy<H&&B[yy][xx]!='N') 552e57677b 2013-06-14 kinaba: mf->addEdge(make_pair(OUT, p), make_pair(IN, make_pair(yy,xx)), 1); 552e57677b 2013-06-14 kinaba: } 552e57677b 2013-06-14 kinaba: if(p!=S && p!=D) 552e57677b 2013-06-14 kinaba: mf->addEdge(make_pair(IN, p), make_pair(OUT, p), 1); 552e57677b 2013-06-14 kinaba: } 552e57677b 2013-06-14 kinaba: int m = mf->calc(make_pair(OUT,S), make_pair(IN,D)); 552e57677b 2013-06-14 kinaba: delete mf; 552e57677b 2013-06-14 kinaba: return m; 552e57677b 2013-06-14 kinaba: } 552e57677b 2013-06-14 kinaba: }; 552e57677b 2013-06-14 kinaba: 552e57677b 2013-06-14 kinaba: // BEGIN CUT HERE 552e57677b 2013-06-14 kinaba: #include <ctime> 552e57677b 2013-06-14 kinaba: double start_time; string timer() 552e57677b 2013-06-14 kinaba: { ostringstream os; os << " (" << int((clock()-start_time)/CLOCKS_PER_SEC*1000) << " msec)"; return os.str(); } 552e57677b 2013-06-14 kinaba: template<typename T> ostream& operator<<(ostream& os, const vector<T>& v) 552e57677b 2013-06-14 kinaba: { os << "{ "; 552e57677b 2013-06-14 kinaba: for(typename vector<T>::const_iterator it=v.begin(); it!=v.end(); ++it) 552e57677b 2013-06-14 kinaba: os << '\"' << *it << '\"' << (it+1==v.end() ? "" : ", "); os << " }"; return os; } 552e57677b 2013-06-14 kinaba: void verify_case(const int& Expected, const int& Received) { 552e57677b 2013-06-14 kinaba: bool ok = (Expected == Received); 552e57677b 2013-06-14 kinaba: if(ok) cerr << "PASSED" << timer() << endl; else { cerr << "FAILED" << timer() << endl; 552e57677b 2013-06-14 kinaba: cerr << "\to: \"" << Expected << '\"' << endl << "\tx: \"" << Received << '\"' << endl; } } 552e57677b 2013-06-14 kinaba: #define CASE(N) {cerr << "Test Case #" << N << "..." << flush; start_time=clock(); 552e57677b 2013-06-14 kinaba: #define END verify_case(_, Block3Checkers().blockThem(board));} 552e57677b 2013-06-14 kinaba: int main(){ 552e57677b 2013-06-14 kinaba: 552e57677b 2013-06-14 kinaba: CASE(0) 552e57677b 2013-06-14 kinaba: string board_[] = {"A......A", 552e57677b 2013-06-14 kinaba: "...N.N..", 552e57677b 2013-06-14 kinaba: ".NNN.NN.", 552e57677b 2013-06-14 kinaba: "NNNN.N.N", 552e57677b 2013-06-14 kinaba: "N.NN.NNN", 552e57677b 2013-06-14 kinaba: ".NNN.NNN", 552e57677b 2013-06-14 kinaba: "NNN...NN", 552e57677b 2013-06-14 kinaba: ".NN.A..N"}; 552e57677b 2013-06-14 kinaba: vector <string> board(board_, board_+sizeof(board_)/sizeof(*board_)); 552e57677b 2013-06-14 kinaba: int _ = 1; 552e57677b 2013-06-14 kinaba: END 552e57677b 2013-06-14 kinaba: CASE(1) 552e57677b 2013-06-14 kinaba: string board_[] = {".....A", 552e57677b 2013-06-14 kinaba: "......", 552e57677b 2013-06-14 kinaba: "......", 552e57677b 2013-06-14 kinaba: "NNNNNN", 552e57677b 2013-06-14 kinaba: "A.....", 552e57677b 2013-06-14 kinaba: "A....."}; 552e57677b 2013-06-14 kinaba: vector <string> board(board_, board_+sizeof(board_)/sizeof(*board_)); 552e57677b 2013-06-14 kinaba: int _ = 100; 552e57677b 2013-06-14 kinaba: END 552e57677b 2013-06-14 kinaba: CASE(2) 552e57677b 2013-06-14 kinaba: string board_[] = {"A.N", 552e57677b 2013-06-14 kinaba: "NNA", 552e57677b 2013-06-14 kinaba: "AN."}; 552e57677b 2013-06-14 kinaba: vector <string> board(board_, board_+sizeof(board_)/sizeof(*board_)); 552e57677b 2013-06-14 kinaba: int _ = 0; 552e57677b 2013-06-14 kinaba: END 552e57677b 2013-06-14 kinaba: CASE(3) 552e57677b 2013-06-14 kinaba: string board_[] = {"......NA", 552e57677b 2013-06-14 kinaba: ".NNNN.N.", 552e57677b 2013-06-14 kinaba: ".N......", 552e57677b 2013-06-14 kinaba: "....NNNN", 552e57677b 2013-06-14 kinaba: "........", 552e57677b 2013-06-14 kinaba: ".N..NNN.", 552e57677b 2013-06-14 kinaba: "......N.", 552e57677b 2013-06-14 kinaba: "A.N....A"} 552e57677b 2013-06-14 kinaba: ; 552e57677b 2013-06-14 kinaba: vector <string> board(board_, board_+sizeof(board_)/sizeof(*board_)); 552e57677b 2013-06-14 kinaba: int _ = 3; 552e57677b 2013-06-14 kinaba: END 552e57677b 2013-06-14 kinaba: /* 552e57677b 2013-06-14 kinaba: CASE(4) 552e57677b 2013-06-14 kinaba: string board_[] = ; 552e57677b 2013-06-14 kinaba: vector <string> board(board_, board_+sizeof(board_)/sizeof(*board_)); 552e57677b 2013-06-14 kinaba: int _ = ; 552e57677b 2013-06-14 kinaba: END 552e57677b 2013-06-14 kinaba: CASE(5) 552e57677b 2013-06-14 kinaba: string board_[] = ; 552e57677b 2013-06-14 kinaba: vector <string> board(board_, board_+sizeof(board_)/sizeof(*board_)); 552e57677b 2013-06-14 kinaba: int _ = ; 552e57677b 2013-06-14 kinaba: END 552e57677b 2013-06-14 kinaba: */ 552e57677b 2013-06-14 kinaba: } 552e57677b 2013-06-14 kinaba: // END CUT HERE