Differences From Artifact [c23044dc81c5002a]:
- File        
SRM/499-U/1C-U.cpp
- 2011-03-20 00:13:20 - part of checkin [2de557d8c0] on branch trunk - 499 (user: kinaba) [annotate]
 
 
To Artifact [4983b441ed2ad4da]:
- File        
SRM/499/1C.cpp
- 2011-10-08 15:42:58 - part of checkin [b57cc94f1b] on branch trunk - Library for SCC added and verified. (user: kinaba) [annotate]
 
 
    15     15   #include <cmath>
    16     16   #include <cassert>
    17     17   #include <cstring>
    18     18   using namespace std;
    19     19   typedef long long LL;
    20     20   typedef complex<double> CMP;
    21     21   
    22         -template<typename V>
    23         -class Graph
           22  +template<typename T>
           23  +class IdGen
    24     24   {
    25         - map<V, int> v2id_;
    26         - vector<V>   id2v_;
           25  + map<T, int> v2id_;
           26  + vector<T>   id2v_;
           27  +public:
           28  + int v2id(const T& v) {
           29  +  if( !v2id_.count(v) ) { v2id_[v] = size(); id2v_.push_back(v); }
           30  +  return v2id_[v];
           31  + }
           32  + const T& id2v(int i) const { return id2v_[i]; }
           33  + int size() const { return id2v_.size(); }
           34  +};
           35  +
           36  +template<typename Vert>
           37  +class SCC
           38  +{
    27     39   public:
           40  + IdGen<Vert> idgen;
    28     41    vector< vector<int> > G;
    29     42   
    30         - int vert( const V& t )
           43  +public:
           44  + void addVert( Vert s_ )
    31     45    {
    32         -  if( !v2id_.count(t) ) { v2id_[t] = G.size(); id2v_.push_back(t); G.resize(G.size()+1); }
    33         -  return v2id_[t];
           46  +  int s = idgen.v2id(s_);
           47  +  if( s >= G.size() ) G.resize(s+1);
    34     48    }
    35         - void edge( const V& s_, const V& t_ )
           49  +
           50  + void addEdge( Vert s_, Vert t_ )
    36     51    {
    37         -  int s=vert(s_), t=vert(t_);
           52  +  int s = idgen.v2id(s_), t = idgen.v2id(t_);
           53  +  if( max(s,t) >= G.size() ) G.resize(max(s,t)+1);
    38     54     G[s].push_back(t);
    39     55    }
    40         - const V& orig( int v )
           56  +
           57  + void scc()
    41     58    {
    42         -  return id2v_[v];
    43         - }
    44         -};
    45         -
    46         -class StronglyConnectedComponent
    47         -{
    48         -public:
    49         - StronglyConnectedComponent( const vector< vector<int> >& G )
    50         -  : scc(), forest(), G(G), no(0), dfs_no(G.size()), dfs_lo(G.size()), scc_id(G.size())
    51         - {
    52         -  for(int v=0; v<G.size(); ++v)
           59  +  int N = G.size();
           60  +  dfs_no.assign(N, 0);
           61  +  dfs_lo.assign(N, 0);
           62  +  pending = stack<int>();
           63  +  scc_id.assign(N, -1);
           64  +  scc_list.clear();
           65  +  scc_children.clear();
           66  +  for(int v=0; v<N; ++v)
    53     67      dfs(v);
    54     68    }
    55     69   
    56         - vector< vector<int> > scc;    // scc[i] : the list of verts in the i-th component
    57         - vector< vector<int> > forest; // the forest structure over sccs
           70  + vector<int> scc_id; // which scc does the vert belong to?
           71  + vector< vector<int> > scc_list;     // list of nodes in the scc
           72  + vector< vector<int> > scc_children; // forest relationship of sccs
    58     73   
    59     74   private:
    60         - const vector< vector<int> >& G;
    61     75    int no;
    62         - vector<int> dfs_no; // Special: 0       : not visited yet
    63         - vector<int> dfs_lo; // Special: INT_MAX : already classified into some scc !!!! not a good idea!
    64         - // rather use scc_id for that purpose (distinguishing assigned or not)
    65         - vector<int> scc_id;
    66         - vector<int> pending;
           76  + vector<int> dfs_no; // 1-origin dfs-visit ID
           77  + vector<int> dfs_lo; // the least ID in the vert's scc
           78  + stack<int> pending; // current unclassigied verts
    67     79   
    68     80    void dfs(int v)
    69     81    {
           82  +  // visit v if not yet
    70     83     if( dfs_no[v] )
    71     84      return;
           85  +  dfs_no[v] = dfs_lo[v] = ++no;
           86  +  pending.push(v);
    72     87   
    73         -  dfs_no[v] = dfs_lo[v] = ++no;    // visit v
    74         -  for(int i=0; i<G[v].size(); ++i) // visit children
    75         -  {
           88  +  // visit children
           89  +  for(int i=0; i<G[v].size(); ++i) {
    76     90      int u = G[v][i];
    77     91      dfs( u );
    78         -   if( !is_already_classified_in_some_scc(u) )
    79         -    dfs_lo[v] = min( dfs_lo[v], dfs_lo[G[v][i]] );
           92  +   if( scc_id[u] == -1 )
           93  +    dfs_lo[v] = min( dfs_lo[v], dfs_lo[u] );
    80     94     }
    81     95   
    82         -  pending.push_back(v);
    83         -  if( dfs_no[v] == dfs_lo[v] ) { // found the representative of a scc
    84         -   // todo: pending -> dfs_lo:=INT_MAX
    85         -   scc.push_back(pending), pending.clear();
           96  +  // when v is the representative of scc
           97  +  if( dfs_no[v] == dfs_lo[v] ) {
           98  +   vector<int> scc;
           99  +   for(;;) {
          100  +    int w = pending.top(); pending.pop();
          101  +    scc.push_back(w);
          102  +    scc_id[w] = scc_list.size();
          103  +    if( w == v ) break;
          104  +   }
          105  +   scc_list.push_back(scc);
    86    106   
    87         -   // construct scc-forest (if needed)
    88         -   scc_id[v] = scc.size()-1;
    89    107      set<int> children;
    90         -   for(int i=0; i<G[v].size(); ++i)
    91         -    if( dfs_lo[G[v][i]] != v )
    92         -     children.insert( scc_id[dfs_lo[G[v][i]]] );
    93         -   forest.push_back( vector<int>(children.begin(), children.end()) );
          108  +   for(int j=0; j<scc.size(); ++j)
          109  +    for(int i=0; i<G[scc[j]].size(); ++i)
          110  +     children.insert( scc_id[G[scc[j]][i]] );
          111  +   children.erase(scc_id[v]);
          112  +   scc_children.push_back( vector<int>(children.begin(), children.end()) );
    94    113     }
    95    114    }
    96    115   };
    97         -
    98    116   
    99    117   class ImpossibleGame { public:
   100    118    static LL C(LL n, LL k) {
   101    119     LL v = 1;
   102    120     for(int i=1; i<=k; ++i)
   103    121      v = v * (n+1-i) / i;
   104    122     return v;
   105    123    }
          124  +
   106    125    static LL weight(LL a, LL b, LL c, LL d) {
   107    126     return C(a+b+c+d,a) * C(b+c+d,b) * C(c+d,c);
   108    127    }
   109    128   
   110    129    long long getMinimum(int k, vector <string> before, vector <string> after)
   111    130    {
   112    131     vector< pair< vector<int>, vector<int> > > dif;
................................................................................
   114    133     {
   115    134      vector<int> be(4), af(4);
   116    135      for(int j=0; j<before[i].size(); ++j) be[before[i][j]-'A'] ++;
   117    136      for(int j=0; j< after[i].size(); ++j) af[ after[i][j]-'A'] ++;
   118    137      dif.push_back( make_pair(be,af) );
   119    138     }
   120    139   
   121         -  Graph< vector<int> > G;
          140  +  SCC< vector<int> > G;
   122    141   
   123    142     vector<int> v(4);
   124    143     for(v[0]=0; v[0]<=k; ++v[0])
   125    144     for(v[1]=0; v[0]+v[1]<=k; ++v[1])
   126    145     for(v[2]=0; v[0]+v[1]+v[2]<=k; ++v[2])
   127         -  for(v[3]=0; v[0]+v[1]+v[2]+v[3]<=k; ++v[3])
   128    146     {
   129         -   G.vert(v);
          147  +   v[3] = k - v[0] - v[1] - v[2];
          148  +   G.addVert(v);
   130    149      for(int i=0; i<dif.size(); ++i)
   131    150      {
   132    151       bool dame = false;
   133    152   
   134    153       vector<int> u = v;
   135    154       for(int k=0; k<4; ++k)
   136    155       {
   137    156        if( (u[k]-=dif[i].first[k]) < 0 )
   138    157         dame = true;
   139    158        u[k] += dif[i].second[k];
   140    159       }
   141    160       if( !dame )
   142         -     G.edge(v, u);
          161  +     G.addEdge(v, u);
   143    162      }
   144    163     }
   145    164   
   146         -  StronglyConnectedComponent scc(G.G);
   147         -  return 0;
          165  +  G.scc();
          166  +
          167  +  LL ans = 0;
          168  +  for(int v=0; v<G.scc_list.size(); ++v)
          169  +   ans = max(ans, rec(v, G));
          170  +  return ans;
          171  + }
          172  +
          173  + map<int, LL> memo;
          174  + LL rec(int v, SCC< vector<int> >& G)
          175  + {
          176  +  if( memo.count(v) )
          177  +   return memo[v];
          178  +  LL mx = 0;
          179  +  for(int i=0; i<G.scc_children[v].size(); ++i)
          180  +   mx = max(mx, rec(G.scc_children[v][i], G));
          181  +  for(int i=0; i<G.scc_list[v].size(); ++i) {
          182  +   const vector<int>& str = G.idgen.id2v(G.scc_list[v][i]);
          183  +   mx += weight(str[0], str[1], str[2], str[3]);
          184  +  }
          185  +  return memo[v] = mx;
   148    186    }
   149    187   };
   150    188   
   151    189   // BEGIN CUT HERE
   152    190   #include <ctime>
   153    191   double start_time; string timer()
   154    192    { ostringstream os; os << " (" << int((clock()-start_time)/CLOCKS_PER_SEC*1000) << " msec)"; return os.str(); }
................................................................................
   162    200    cerr << "\to: \"" << Expected << '\"' << endl << "\tx: \"" << Received << '\"' << endl; } }
   163    201   #define CASE(N) {cerr << "Test Case #" << N << "..." << flush; start_time=clock();
   164    202   #define END  verify_case(_, ImpossibleGame().getMinimum(k, before, after));}
   165    203   int main(){
   166    204   
   167    205   CASE(0)
   168    206    int k = 1;
   169         - string before_[] = { "A" }
   170         -;
          207  + string before_[] = { "A" };
   171    208      vector <string> before(before_, before_+sizeof(before_)/sizeof(*before_));
   172         - string after_[] = { "B" }
   173         -;
          209  + string after_[] = { "B" };
   174    210      vector <string> after(after_, after_+sizeof(after_)/sizeof(*after_));
   175    211    long long _ = 2LL;
   176    212   END
   177    213   CASE(1)
   178    214    int k = 2;
   179         - string before_[] = { "A", "A", "D" }
   180         -;
          215  + string before_[] = { "A", "A", "D" };
   181    216      vector <string> before(before_, before_+sizeof(before_)/sizeof(*before_));
   182         - string after_[] = { "B", "C", "D" }
   183         -;
          217  + string after_[] = { "B", "C", "D" };
   184    218      vector <string> after(after_, after_+sizeof(after_)/sizeof(*after_));
   185    219    long long _ = 5LL;
   186    220   END
   187    221   CASE(2)
   188    222    int k = 2;
   189         - string before_[] = { "B", "C", "D" }
   190         -;
          223  + string before_[] = { "B", "C", "D" };
   191    224      vector <string> before(before_, before_+sizeof(before_)/sizeof(*before_));
   192         - string after_[] = { "C", "D", "B" }
   193         -;
          225  + string after_[] = { "C", "D", "B" };
   194    226      vector <string> after(after_, after_+sizeof(after_)/sizeof(*after_));
   195    227    long long _ = 9LL;
   196    228   END
   197    229   CASE(3)
   198    230    int k = 6;
   199         - string before_[] = { "AABBC", "AAAADA", "AAACA", "CABAA", "AAAAAA", "BAAAA" }
   200         -;
          231  + string before_[] = { "AABBC", "AAAADA", "AAACA", "CABAA", "AAAAAA", "BAAAA" };
   201    232      vector <string> before(before_, before_+sizeof(before_)/sizeof(*before_));
   202         - string after_[] = { "AACCB", "DAAABC", "AAAAD", "ABCBA", "AABAAA", "AACAA" }
   203         -;
          233  + string after_[] = { "AACCB", "DAAABC", "AAAAD", "ABCBA", "AABAAA", "AACAA" };
   204    234      vector <string> after(after_, after_+sizeof(after_)/sizeof(*after_));
   205    235    long long _ = 499LL;
   206    236   END
   207         -/*
   208    237   CASE(4)
   209         - int k = ;
   210         - string before_[] = ;
          238  + int k = 7;
          239  + string before_[] = {"BDBBB", "ACBBBBC", "BBBBC", "CCACCCB", "CC", "BBBBBBD", "BBDBBAB", "DBBCBB", "DBABABB", "BBBBABB", "BBBBB", "BBABB", "BBBBBDB", "ABDC", "BDBBDCB", "BBBBBAC", "BBBDBC", "BBBBBBA", "BBBBBBB", "BACCBB", "ABBDABB", "DC", "ABBDBB", "ACBCABB"};
   211    240      vector <string> before(before_, before_+sizeof(before_)/sizeof(*before_));
   212         - string after_[] = ;
          241  + string after_[] = {"BADBC", "ACDBCBB", "BADCB", "BBBDBBC", "BD", "BBACCBD", "BBADBDB", "BBBBCC", "BBBCBBB", "BCBDCBD", "ABBBA", "DDBAB", "BCBDBDB", "BBCB", "BBCBBBB", "BABCBDB", "BBCCBD", "BBBBBCB", "DBCBADC", "BBBACA", "ABBABBC", "DB", "DBBCBB", "BBDBBBB"};
   213    242      vector <string> after(after_, after_+sizeof(after_)/sizeof(*after_));
   214         - long long _ = LL;
          243  + long long _ = 7112LL;
   215    244   END
          245  +/*
   216    246   CASE(5)
   217    247    int k = ;
   218    248    string before_[] = ;
   219    249      vector <string> before(before_, before_+sizeof(before_)/sizeof(*before_));
   220    250    string after_[] = ;
   221    251      vector <string> after(after_, after_+sizeof(after_)/sizeof(*after_));
   222    252    long long _ = LL;
   223    253   END
   224    254   */
   225    255   }
   226    256   // END CUT HERE