题目
给定一个图的N个节点和节点之间的M条边,数据保证该图可以构成一个二分图。求该二分图最大匹配。
题目链接:二分图最大匹配
首先通过染色法,将图的N个节点分成两个部分;然后通过匈牙利算法求二分图的最大匹配。
实现
#include<stdio.h> #include<string.h> #include<iostream> #include<string> #include<set> #include<map> #include<vector> #include<queue> #include<stack> #include<unordered_map> #include<unordered_set> #include<algorithm> using namespace std; struct Edge{ int to; int next; }; Edge gEdges[80005]; int gEdgeIndex; int gHead[10005]; int gMatch[10005]; bool gVisited[10005]; int gColor[10005]; bool conflict; void Init(){ gEdgeIndex = 0; memset(gHead, -1, sizeof(gHead)); memset(gVisited, false, sizeof(gVisited)); memset(gMatch, -1, sizeof(gMatch)); memset(gColor, -1, sizeof(gColor)); conflict = false; } void InsertEdge(int u, int v){ int e = gEdgeIndex++; gEdges[e].to = v; gEdges[e].next = gHead[u]; gHead[u] = e; } void PaintColor(int node, int c){ if (conflict) return; gColor[node] = c; for (int e = gHead[node]; e != -1; e = gEdges[e].next){ int x = gEdges[e].to; if (gColor[x] == c){ conflict = true; return; } if (gColor[x] == -1) PaintColor(x, 1 - c); } } bool Dfs(int node){ for (int e = gHead[node]; e != -1; e = gEdges[e].next){ int v = gEdges[e].to; if (!gVisited[v]){ gVisited[v] = true; //置位 if (gMatch[v] == -1){ //如果对方的阵营中v点还没有匹配,则成功找到一条交错路径 gMatch[node] = v; gMatch[v] = node; return true; } else if (Dfs(gMatch[v])){ //如果对方阵营中v有匹配点,匹配点肯定在己方阵营,则继续从己方阵营的点 //递归 gMatch[node] = v; gMatch[v] = node; return true; } } } return false; } int main(){ int n, m, u, v; Init(); scanf("%d %d", &n, &m); for (int i = 0; i < m; i++){ scanf("%d %d", &u, &v); InsertEdge(u, v); InsertEdge(v, u); } for (int i = 1; i <= n; i++) if (gColor[i] == -1) PaintColor(i, 0); int ans = 0; for (int i = 1; i <= n; i++){ if (gColor[i] == 0 && gMatch[i] == -1){//从固定一方阵营中,不断找未匹配点 //寻找交错路,找到一条交错路,则匹配个数增加1 memset(gVisited, false, sizeof(gVisited)); if (Dfs(i)) ans++; } } printf("%d\n", ans); return 0; }
时间: 2024-10-06 13:13:16