Wednesday, September 11, 2019

[Codemarshal] B. Just change it up so it doesn't look like you copied...

Author            : Dipu Kumar Mohanto 
                    CSE, Batch - 6
                    BRUR.
Problem Statement : B. Just change it up so it doesn't look like you copied...
Source            : Codemarshal
                    Kuet IUPC'19
Category          : Graph Theory
Algorithm         : Min Cost Max Flow, Lexicographical Min Cost Max Flow
Verdict           : Accepted

  1. #include "bits/stdc++.h"  
  2.   
  3. using namespace std;  
  4.   
  5. static const int maxn = 15 + 5;  
  6. static const int Max = 1000 + 5;  
  7.   
  8. string paragraph[maxn];  
  9. vector <string> sentence[maxn];  
  10. vector <string> allSentences;  
  11. vector <int> priority[maxn];  
  12. vector <int> which[Max];  
  13. map <string, int> mapper;  
  14. map <int, string> rmapper;  
  15.   
  16. struct Edge  
  17. {  
  18.       int to;  
  19.       int flow;  
  20.       int cap;  
  21.       int cost;  
  22.       int rev;  
  23.       Edge(int to = 0, int flow = 0, int cap = 0, int cost = 0, int rev = 0)  
  24.             : to(to)  
  25.             , flow(flow)  
  26.             , cap(cap)  
  27.             , cost(cost)  
  28.             , rev(rev) {}  
  29. };  
  30.   
  31. struct MinCostMaxFlow  
  32. {  
  33.       int nodes;  
  34.       vector <int> prio;  
  35.       vector <int> curflow;  
  36.       vector <int> prevEdge;  
  37.       vector <int> prevnode;  
  38.       vector <int> q;  
  39.       vector <int> pot;  
  40.       vector <bool> inqueue;  
  41.       vector< vector<Edge> > graph;  
  42.   
  43.       MinCostMaxFlow() {}  
  44.       MinCostMaxFlow(int n)  
  45.             : nodes(n)  
  46.             , prio(n, 0)  
  47.             , curflow(n, 0)  
  48.             , prevEdge(n, 0)  
  49.             , prevnode(n, 0)  
  50.             , q(n, 0)  
  51.             , pot(n, 0)  
  52.             , inqueue(n, 0)  
  53.             , graph(n) {}  
  54.   
  55.       void addEdge(int source, int to, int capacity, int cost)  
  56.       {  
  57.             Edge a = {to, 0, capacity, cost, (int)graph[to].size()};  
  58.             Edge b = {source, 0, 0, -cost, (int)graph[source].size()};  
  59.             graph[source].push_back(a);  
  60.             graph[to].push_back(b);  
  61.       }  
  62.       void bellman_ford(int source, vector<int> &dist)  
  63.       {  
  64.             fill(dist.begin(), dist.end(), INT_MAX);  
  65.             dist[source] = 0;  
  66.             int qt=0;  
  67.             q[qt++] = source;  
  68.             for(int qh = 0;(qh-qt) % nodes != 0; qh++)  
  69.             {  
  70.                   int u = q[qh % nodes];  
  71.                   inqueue[u] = false;  
  72.                   for(auto &e : graph[u])  
  73.                   {  
  74.                         if(e.flow >= e.cap) continue;  
  75.                         int v = e.to;  
  76.                         int newDist = dist[u] + e.cost;  
  77.                         if(dist[v] > newDist)  
  78.                         {  
  79.                               dist[v] = newDist;  
  80.                               if(!inqueue[v])  
  81.                               {  
  82.                                     inqueue[v] = true;  
  83.                                     q[qt++ % nodes] = v;  
  84.                               }  
  85.                         }  
  86.                   }  
  87.             }  
  88.       }  
  89.       pair<intint> minCostFlow(int source, int dest, int maxflow)  
  90.       {  
  91.             bellman_ford(source, pot);  
  92.             int flow = 0;  
  93.             int flow_cost = 0;  
  94.             while(flow < maxflow)  
  95.             {  
  96.                   priority_queue< pair<intint>, vector< pair<intint> >, greater< pair<intint> > > q;  
  97.                   q.push({0, source});  
  98.                   fill(prio.begin(), prio.end(), INT_MAX);  
  99.                   prio[source] = 0;  
  100.                   curflow[source] = INT_MAX;  
  101.                   while(!q.empty())  
  102.                   {  
  103.                         int d = q.top().first;  
  104.                         int u = q.top().second;  
  105.                         q.pop();  
  106.                         if(d != prio[u]) continue;  
  107.                         for(int i = 0; i < graph[u].size(); i++)  
  108.                         {  
  109.                               Edge &e=graph[u][i];  
  110.                               int v = e.to;  
  111.                               if(e.flow >= e.cap) continue;  
  112.                               int newPrio = prio[u] + e.cost + pot[u] - pot[v];  
  113.                               if(prio[v] > newPrio)  
  114.                               {  
  115.                                     prio[v] = newPrio;  
  116.                                     q.push({newPrio, v});  
  117.                                     prevnode[v] = u;  
  118.                                     prevEdge[v] = i;  
  119.                                     curflow[v] = min(curflow[u], e.cap - e.flow);  
  120.                               }  
  121.                         }  
  122.                   }  
  123.                   if(prio[dest] == INT_MAX) break;  
  124.                   for(int i = 0;i < nodes; i++) pot[i] += prio[i];  
  125.                   int df = min(curflow[dest], maxflow - flow);  
  126.                   flow += df;  
  127.                   for(int v = dest; v!= source; v = prevnode[v])  
  128.                   {  
  129.                         Edge &e = graph[ prevnode[v] ][ prevEdge[v] ];  
  130.                         e.flow += df;  
  131.                         graph[v][e.rev].flow -= df;  
  132.                         flow_cost += df * e.cost;  
  133.                   }  
  134.             }  
  135.             return {flow, flow_cost};  
  136.       }  
  137.       int flow(int u)  
  138.       {  
  139.             int maxi = 0;  
  140.             for (Edge g : graph[u]) maxi = max(maxi, g.flow);  
  141.             return maxi;  
  142.       }  
  143. };  
  144.   
  145. void clean()  
  146. {  
  147.       mapper.clear();  
  148.       rmapper.clear();  
  149.       allSentences.clear();  
  150.       for (int i = 0; i < maxn; i++)  
  151.       {  
  152.             priority[i].clear();  
  153.             sentence[i].clear();  
  154.       }  
  155.       for (int i = 0; i < 1000 + 5; i++)  
  156.       {  
  157.             which[i].clear();  
  158.       }  
  159. }  
  160.   
  161. signed main()  
  162. {  
  163.       ios_base::sync_with_stdio(false);  
  164.       cin.tie(nullptr);  
  165.       cout.tie(nullptr);  
  166.   
  167. //      #ifndef ONLINE_JUDGE  
  168. //            freopen("in.txt", "r", stdin);  
  169. //      #endif // ONLINE_JUDGE  
  170.   
  171.       int tc;  
  172.       cin >> tc;  
  173.       for (int tcase = 1; tcase <= tc; tcase++)  
  174.       {  
  175.             clean();  
  176.             int n;  
  177.             cin >> n;  
  178.             for (int i = 1; i <= n; i++)  
  179.             {  
  180.                   cin >> paragraph[i];  
  181.                   string s;  
  182.                   for (char ch : paragraph[i])  
  183.                   {  
  184.                         if (ch == '.')  
  185.                         {  
  186.                               assert(s.empty() == false);  
  187.                               sentence[i].push_back(s);  
  188.                               allSentences.push_back(s);  
  189.                               s.clear();  
  190.                         }  
  191.                         else  
  192.                         {  
  193.                               s.push_back(ch);  
  194.                         }  
  195.                   }  
  196.                   if (s.empty() == false)  
  197.                   {  
  198.                         sentence[i].push_back(s);  
  199.                         allSentences.push_back(s);  
  200.                         s.clear();  
  201.                   }  
  202.             }  
  203.             int k;  
  204.             cin >> k;  
  205.             sort(allSentences.begin(), allSentences.end());  
  206.             int ptr = 0;  
  207.             for (string str : allSentences)  
  208.             {  
  209.                   if (mapper.find(str) == mapper.end())  
  210.                   {  
  211.                         mapper[str] = ++ptr;  
  212.                         rmapper[ptr] = str;  
  213.                   }  
  214.             }  
  215.             for (int i = 1; i <= n; i++)  
  216.             {  
  217.                   for (int j = 0; j < sentence[i].size(); j++)  
  218.                   {  
  219.                         priority[i].push_back(mapper[ sentence[i][j] ]);  
  220.                   }  
  221.                   sort(priority[i].begin(), priority[i].end());  
  222.                   for (int x : priority[i]) which[x].push_back(i);  
  223.             }  
  224.             int nodes = 3 + n + ptr;  
  225.             MinCostMaxFlow mcmf(nodes);  
  226.             int source = 0;  
  227.             int sink = nodes - 2;  
  228.             int superSink = nodes - 1;  
  229.             for (int i = 1; i <= n; i++)  
  230.             {  
  231.                   mcmf.addEdge(source, i, 1, 0);  
  232.                   for (int j = 0; j < priority[i].size(); j++)  
  233.                   {  
  234.                         mcmf.addEdge(i, n + priority[i][j], 1, priority[i][j]);  
  235.                   }  
  236.             }  
  237.             for (int i = 1; i <= ptr; i++)  
  238.             {  
  239.                   mcmf.addEdge(n + i, sink, 1, 0);  
  240.             }  
  241.             mcmf.addEdge(sink, superSink, 1000, 0);  
  242.             pair <intint> maxFlow = mcmf.minCostFlow(source, superSink, 1000);  
  243.             vector <int> sol;  
  244.             for (int i = 1; i <= ptr; i++)  
  245.             {  
  246.                   int flow = mcmf.flow(n + i);  
  247.                   if (flow == 1) sol.push_back(i);  
  248.             }  
  249.             vector <bool> vis(n + 1, 0);  
  250.             vector <int> res;  
  251.             for (int x : sol)  
  252.             {  
  253.                   if (res.size() == k) break;  
  254.                   bool ok = false;  
  255.                   for (int y : which[x])  
  256.                   {  
  257.                         if (vis[y]) ok = true;  
  258.                   }  
  259.                   if (ok) continue;  
  260.                   res.push_back(x);  
  261.                   for (int y : which[x]) vis[y] = 1;  
  262.             }  
  263.             cout << "Case " << tcase << ": ";  
  264.             if (res.size() < k)  
  265.             {  
  266.                   cout << "impossible\n";  
  267.             }  
  268.             else  
  269.             {  
  270.                   for (int i = 0; i < k; i++)  
  271.                   {  
  272.                         cout << rmapper[ res[i] ];  
  273.                         if (i == k - 1) cout << '\n';  
  274.                         else cout << ".";  
  275.                   }  
  276.             }  
  277.       }  
  278. }  

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.