标签:style blog io color ar os for sp div
匈牙利算法,求二分图最大匹配。
若P是图G中一条连通两个未匹配顶点的路径,并且属于M的边和不属于M的边(即已匹配和待匹配的边)在P上交替出现,则称P为相对于M的一条增广路径。(M为一个匹配)
由增广路的定义可以推出下述三个结论:
1 #include <iostream> 2 #include <cstdio> 3 #include <vector> 4 5 using namespace std; 6 7 bool augment(vector<vector<int> > &adj, int node, 8 vector<bool> &visited, vector<int> &matches) { 9 for (auto neig : adj[node]) { 10 if (!visited[neig]) { 11 visited[neig] = true; 12 if (matches[neig] == -1 || augment(adj, matches[neig], visited, matches)) { 13 matches[neig] = node; 14 return true; 15 } 16 } 17 } 18 return false; 19 } 20 21 int hungary(vector<vector<int> > &adj, vector<int> &first) { 22 vector<bool> visited; 23 vector<int> matches(adj.size(), -1); 24 int count = 0; 25 for (auto f : first) { 26 visited.assign(adj.size(), false); 27 if (augment(adj, f, visited, matches)) { 28 count++; 29 } 30 } 31 for (int i = 0; i < adj.size(); ++i) { 32 cout << i << "<->" << matches[i] << endl; 33 } 34 return count; 35 } 36 37 int main(int argc, char** argv) { 38 freopen("input.txt", "r", stdin); 39 int first, n, m; 40 cin >> n >> first >> m; 41 vector<vector<int> > adj(n); 42 vector<int> left; 43 for (int i = 0; i < first; ++i) { 44 int l; 45 cin >> l; 46 left.push_back(l); 47 } 48 for (int i = 0; i < m; ++i) { 49 int n1, n2; 50 cin >> n1 >> n2; 51 adj[n1].push_back(n2); 52 adj[n2].push_back(n1); 53 } 54 55 cout << hungary(adj, left) << endl; 56 return 0; 57 }
假设左边结点个数为n, 右边结点个数为m,这里用了visited来确保右边的点不会重复访问,时间复杂度还是是O(nmn),如果把邻接表用list而不是vector的话,访问过的右边结点删去,那么开销可以在O(nm)了。因为右边结点只需访问一次。
空间复杂度是O(m+n)。
标签:style blog io color ar os for sp div
原文地址:http://www.cnblogs.com/linyx/p/4069088.html