Advertisement
Alex_tz307

Cuplaj maxim in graf bipartit

Jan 19th, 2021
220
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.61 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2.  
  3. using namespace std;
  4.  
  5. ifstream fin("cuplaj.in");
  6. ofstream fout("cuplaj.out");
  7.  
  8. /*
  9. https://www.youtube.com/watch?v=GhjwOiJ4SqU
  10.  
  11. In order to solve the problem we first need to build a flow network.
  12. Just as we did in the multiple-source multiple-sink problem we will add two “dummy” vertices:
  13. a super-source and a super-sink, and we will draw an edge from the super-source to each of
  14. the vertices in set A(employees in the example above) and from each vertex in set B to the
  15. super-sink. In the end, each unit of flow will be equivalent to a match between an employee
  16. and a job, so each edge will be assigned a capacity of 1. If we would have assigned a
  17. capacity larger than 1 to an edge from the super-source, we could have assigned more than
  18. one job to an employee. Likewise, if we would have assigned a capacity larger than 1 to an
  19. edge going to the super-sink, we could have assigned the same job to more than one employee.
  20. The maximum flow in this network will give us the cardinality of the maximum matching.
  21. It is easy to find out whether a vertex in set B is matched with a vertex x in set A as well.
  22. We look at each edge connecting x to a vertex in set B, and if the flow is positive along one
  23. of them, there exists a match. As for the running time, the number of augmenting paths is
  24. limited by min(|A|,|B|), where by |X| is denoted the cardinality of set X, making the running
  25. time O(N * M), where N is the number of vertices, and M the number of edges in the graph.
  26.  
  27. An implementation point of view is in place. We could implement the maximum
  28. bipartite matching just like in the pseudocode given earlier. Usually though, we might want
  29. to consider the particularities of the problem before getting to the implementation part,
  30. as they can save time or space. In this case, we could drop the 2-dimensional array that
  31. stored the residual network and replace it with two one-dimensional arrays: one of them
  32. stores the match in set B(or a sentinel value if it doesn’t exist) for each element of set A,
  33. while the other is the other way around. Also, notice that each augmenting path has
  34. capacity 1, as it contributes with just a unit of flow. Each element of set A can be the
  35. first(well, the second, after the super-source) in an augmenting path at most once, so we
  36. can just iterate through each of them and try to find a match in set B. If an augmenting path
  37. exists, we follow it. This might lead to de-matching other elements along the way,
  38. but because we are following an augmenting path, no element will eventually remain unmatched
  39. in the process.
  40. */
  41.  
  42. const int NMAX = 1e4 + 4;
  43. vector<int> G[NMAX];
  44. int l[NMAX], r[NMAX];
  45. bool viz[NMAX];
  46.  
  47. bool dfs(const int &u) {
  48.     if(viz[u])
  49.         return false;
  50.     viz[u] = true;
  51.     for(const int &v : G[u])
  52.         if(!r[v]) {
  53.             l[u] = v;
  54.             r[v] = u;
  55.             return true;
  56.         }
  57.     for(const int &v : G[u])
  58.         if(dfs(r[v])) {
  59.             l[u] = v;
  60.             r[v] = u;
  61.             return true;
  62.         }
  63.     return false;
  64. }
  65.  
  66. int main() {
  67.     int N, M, E;
  68.     fin >> N >> M >> E;
  69.     while(E--) {
  70.         int u, v;
  71.         fin >> u >> v;
  72.         G[u].emplace_back(v);
  73.     }
  74.     for(bool change = true; change; ) {
  75.         change = false;
  76.         memset(viz, false, sizeof(viz));
  77.         for(int node = 1; node <= N; ++node)
  78.             if(!l[node])
  79.                 change |= dfs(node);
  80.     }
  81.     int cuplaj = 0;
  82.     for(int i = 1; i <= N; ++i)
  83.         cuplaj += (l[i] > 0);
  84.     fout << cuplaj << '\n';
  85.     for(int i = 1; i <= N; ++i)
  86.         if(l[i] > 0)
  87.             fout << i << ' ' << l[i] << '\n';
  88. }
  89.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement