Advertisement
Guest User

??

a guest
Feb 19th, 2018
69
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.68 KB | None | 0 0
  1. #include <algorithm>
  2. #include <bitset>
  3. #include <cmath>
  4. #include <cstdio>
  5. #include <cstring>
  6. #include <deque>
  7. #include <functional>
  8. #include <iomanip>
  9. #include <iostream>
  10. #include <queue>
  11. #include <map>
  12. #include <numeric>
  13. #include <set>
  14. #include <sstream>
  15. #include <stack>
  16. #include <utility>
  17. #include <vector>
  18.  
  19. #define INF 1000000000
  20. #define FOR(i, a, b) for(int i=int(a); i<int(b); i++)
  21. #define FORC(cont, it) for(decltype((cont).begin()) it = (cont).begin(); it != (cont).end(); it++)
  22. #define pb push_back
  23.  
  24. using namespace std;
  25.  
  26. typedef long long ll;
  27. typedef pair<int, int> ii;
  28. typedef vector<int> vi;
  29. typedef vector<ii> vii;
  30. typedef vector<vi> vvi;
  31.  
  32. // Maximum Bipartite Matching
  33. // Dados 2 subsets y sus conexiones cual es la mayor cantidad de parejas que se pueden formar?
  34. // Variacion: solo hay 1 subset y las parejas se tienen que formar dentro de el.
  35.  
  36. // Problema diferente a MBM
  37. // Cada edge tiene un costo: Algoritmo Hungaro
  38. // Es un MBM pero con costo cada edge
  39.  
  40. #define maxN 1000
  41.  
  42. int N, L[maxN], R[maxN], u[maxN], v[maxN], pre[maxN];
  43. vi edges[maxN];
  44.  
  45. // O(V*E)
  46. // Easy to code
  47. bool dfs(int n) {
  48.     if (v[n]) return false;
  49.     v[n] = true;
  50.     FOR(i, 0, edges[n].size()) {
  51.         int e = edges[n][i];
  52.         if (R[e] == -1 || dfs(R[e])) {
  53.             L[n] = e;
  54.             R[e] = n;
  55.             return true;
  56.         }
  57.     }
  58.     return false;
  59. }
  60.  
  61. ii rev[maxN];
  62. int q[maxN];
  63.  
  64. int match() {
  65.     int qc = 0, ret = 0;
  66.     memset(rev, -1, sizeof(rev));
  67.     memset(u, false, sizeof(u));
  68.     memset(v, false, sizeof(v));
  69.     FOR(i, 0, N) {
  70.         if (!~R[i]) q[qc++] = i, v[i] = true;
  71.     }
  72.     FOR(i, 0, qc) {
  73.         int n = q[i];
  74.         FOR(j, 0, edges[n].size()) {
  75.             int to = edges[n][j];
  76.             if (!~R[to]) {
  77.                 int tf = n;
  78.                 bool vv = true;
  79.                 while (~tf) {
  80.                     if (u[tf]) {
  81.                         vv = false;
  82.                         break;
  83.                     }
  84.                     u[tf] = true;
  85.                     tf = rev[tf].first;
  86.                 }
  87.                 if (vv) {
  88.                     tf = n;
  89.                     while (~tf) {
  90.                         L[tf] = to;
  91.                         R[to] = tf;
  92.                         to = rev[tf].second;
  93.                         tf = rev[tf].first;
  94.                     }
  95.                     ret++;
  96.                 }
  97.             }
  98.             else if (!v[R[to]]) {
  99.                 rev[R[to]] = ii(n, to);
  100.                 v[R[to]] = true;
  101.                 q[qc++] = R[to];
  102.             }
  103.         }
  104.     }
  105.     return ret;
  106. }
  107.  
  108. // sqrt(V)*E
  109. // Harder to code, but easy to transform from MBM BFS, and it's faster
  110. // 99% of the time, this won't be needed and DFS is more than enough, use this if constraints are super tight
  111. int bfs() {
  112.     int ret = 0;
  113.     queue<int> q;
  114.     memset(v, 0, sizeof(v));
  115.     FOR(i, 0, N) {
  116.         u[i] = 0;
  117.         pre[i] = -2;
  118.         if (L[i] == -1) {
  119.             q.push(i);
  120.             pre[i] = -1;
  121.         }
  122.     }
  123.     while (!q.empty()) {
  124.         int f = q.front();
  125.         q.pop();
  126.         FOR(i, 0, edges[f].size()) {
  127.             int next = edges[f][i];
  128.             if (R[next] == -1) {
  129.                 int tf = f, tnext = next, m = 0;
  130.                 while (tf >= 0 && !m) {
  131.                     m |= u[tf] | v[tnext];
  132.                     u[tf] = v[tnext] = 1;
  133.                     tnext = L[tf];
  134.                     tf = pre[tf];
  135.                 }
  136.                 if (m) continue;
  137.                 while (f >= 0) {
  138.                     R[next] = f;
  139.                     tnext = next;
  140.                     next = L[f];
  141.                     L[f] = tnext;
  142.                     f = pre[f];
  143.                 }
  144.                 ret++;
  145.             }
  146.             else {
  147.                 int ol = R[next];
  148.                 if (pre[ol] == -2) {
  149.                     q.push(ol);
  150.                     pre[ol] = f;
  151.                 }
  152.             }
  153.         }
  154.     }
  155.     return ret;
  156. }
  157.  
  158. int main() {
  159.     // Just to see max amount of times bfs MBM was called
  160.     int hi = 0;
  161.     FOR(i, 0, 1000) {
  162.         N = rand() % 100 + 1;
  163.         int M = rand() % 100 + 1;
  164.         FOR(j, 0, N) {
  165.             edges[j].clear();
  166.             int k = rand() % 20;
  167.             FOR(kk, 0, k) {
  168.                 edges[j].push_back(rand() % M);
  169.             }
  170.         }
  171.         // MBM DFS
  172.         memset(L, -1, sizeof(L));
  173.         memset(R, -1, sizeof(R));
  174.         int ans1 = 0;
  175.         FOR(j, 0, N) {
  176.             memset(v, false, sizeof(v));
  177.             if (dfs(j)) ans1++;
  178.         }
  179.        
  180.         // MBM BFS
  181.         int t, ans2 = 0;
  182.         memset(L, -1, sizeof(L));
  183.         memset(R, -1, sizeof(R));
  184.         // thi corresponds to the amount of times we need to iterate through the entire graph, which is going to be smaller than 2*sqrt(N)
  185.         int thi = 0;
  186.         while ((t = match())) {
  187.         //while ((t = bfs())) {
  188.             ans2 += t;
  189.             thi++;
  190.         }
  191.         hi = max(hi, thi);
  192.         // In theory this line should never be true
  193.         if (ans1 != ans2) {
  194.             cerr << "Error" << endl;
  195.             cout << "Error" << endl;
  196.         }
  197.     }
  198.     cout << hi << endl;
  199.    
  200.     // Game theory:
  201.  
  202.     // Hay 2 maneras de pensarlos
  203.     // 1) Standard Recursive
  204.     // Al menos 1 lose-> win (es decir si te puedes mover a una posicion perdedora estas en una ganadora, puesto que te moveras a la perdedora y sera el turno de tu oponente)
  205.     // 0 lose y al menos 1 draw -> draw (si no te puedes mover a una posicion perdedora pero si a una de empate te mueves ahi, para empatar)
  206.     // 0 lose y 0 draw -> lose (si solo te puedes mover a posiciones ganadoras es una posicion perdedora ya que el oponente quedara en posicion ganadora)
  207.  
  208.     // 2) BFS (Eratosthenes logic)
  209.     // lose -> win (if not in Q, push to Q)
  210.     // if all states x can visit are true, then x is lose (push x to Q)
  211.     // Once Q is empty, all states that are neither win or lose are draw
  212.  
  213.     // Grundy numbers:
  214.     // El valor de cada posicion es el primer valor al cual no podemos llegar desde dicho estado (notar que cada valor son numeros enteros >=0)
  215.     // 0 indica un estado que pierde, cualquier otro es un estado ganador.
  216.     // Por ejemplo si tenemos una pila con 10 piedras y se tienen que quitar entre 1 y 4 piedras, y el que quite la ultima piedra gana:
  217.     // Piedras Valor
  218.     // 0       0
  219.     // 1       1
  220.     // 2       2
  221.     // 3       3
  222.     // 4       4
  223.     // 5       0 (notar que lleva a estados 1, 2, 3 y 4, pero no existe valor 0, por ende vale 0)
  224.     // 6       1
  225.     // 7       2
  226.     // 8       3
  227.     // 9       4
  228.     // 10      0 (notar que hay un patron)
  229.  
  230.     // Cuando tenemos muchos subjuegos, cada uno con su propio grundy number, podemos hacer xor entre todos ellos y eso establece el nuevo grundy number.
  231.     // Por ejemplo si tenemos 2 pilas de piedritas, una con 2 y la otra con 3 el grundy number se vuelve 1 (2^3==1)
  232.     return 0;
  233. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement