#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define maxn 10010
#define maxm 2000000
using namespace std;
struct Edge{
int u, v;
int Next;
}e[maxm];
int n, m, fi[maxn], ecnt;
int link[maxn]; //记录x中的结点与哪个点相连
int cy[maxn]; //y中点的第i个是哪个点
int use_if[maxn]; //x中的某个点是否被用过
int xn = 1, yn;
bool from[maxn];//记录一个点位于哪个集合之中
void add_edge(int u, int v) {
ecnt++;
e[ecnt].u = u, e[ecnt].v = v;
e[ecnt].Next = fi[u], fi[u] = ecnt;
}
int dfs(int x) {
for(int i = fi[x]; i != -1; i = e[i].Next) {
int v = e[i].v;
if(!use_if[v]) {
use_if[v] = 1;
if(link[v] == -1|| dfs(link[v])) { //注意理解 这是核心
link[v] = x;
return 1;
}
}
}
return 0;
}
int max_match() {
int ans = 0;
for(int i = 1; i <= yn; i++) {
memset(use_if, false, sizeof(use_if));
ans += dfs(cy[i]);
}
return ans;
}
void bfs() { //bfs染色
int q[maxn], head = 0, tail = 1;
bool in_q[maxn];
memset(q, 0, sizeof(q));
memset(in_q, false, sizeof(in_q));
q[0] = 1;
in_q[1] = true, from[1] = true;
while(head < tail) {
int x = q[head];
for(int i = fi[x]; i != -1; i = e[i].Next) {
int v = e[i].v;
if(!in_q[v]) {
q[tail++] = v;
in_q[v] = true;
from[v] = !from[x];
if(from[v])
xn++;
else
cy[++yn] = v;
}
}
head++;
}
}
int main() {
memset(fi, -1, sizeof(fi));
memset(link, -1, sizeof(link));
scanf("%d%d", &n, &m);
for(int i = 1; i <= m; i++) {
int u, v;
scanf("%d%d", &u, &v);
add_edge(u, v);
add_edge(v, u);
}
bfs();
cout << max_match() << endl;
return 0;
}
二分图匹配
最新推荐文章于 2023-03-26 12:11:15 发布